hdu2680(最短路spfa!此题有重大发现)
Each case begins with three integers n, m and s,(n<1000,m<20000,1=<s<=n) n stands for the number of bus stations in this city and m stands for the number of directed ways between bus stations .(Maybe there are several ways between two bus stations .) s stands for the bus station that near Kiki’s friend’s home.
Then follow m lines ,each line contains three integers p , q , t (0<t<=1000). means from station p to station q there is a way and it will costs t minutes .
Then a line with an integer w(0<w<n), means the number of stations Kiki can take at the beginning. Then follows w integers stands for these stations.
5 8 5 1 2 2 1 5 3 1 3 4 2 4 7 2 5 6 2 3 5 3 5 1 4 5 1 2 2 3 4 3 4 1 2 3 1 3 4 2 3 2 1 1
1 -1
题意是先输入三个数,分别表示总共公交站台个数n,公交车路线个数m,目的地的公交站台s,然后输入m个公交线路,一对边和权值,然后输入一个数w表示最初能去的公交站台的个数,接下来w个数分别是最初可以到达的公交站台;求到达目的地s的最短时间(最小权值)。题目一看就知道是最短路,不过显然这题与别的题目有点不一样的是初始站台很多个,目标站台只有一个,这种情况对于像我这种只会spfa的弱鸡可怎么办好,如果把所有的初始站台都来一遍spfa那最坏情况999次,在乘以每一次的spfa时间复杂度那真是够我受的了,于是,机智的弱鸡想到了一个好办法,这题不就是求很多源点到一个点的最短路径吗,我们如果把题目给我们的初始边反转,反过来不就是求目标点到所有源点的最短路径吗?所以这样子就直接把问题化简为了只调用一次spfa,正在弱鸡兴奋之余,一股脑敲完代码就提交了,于是一股脑的脑残TLE了,弱鸡想想,哎哟,不对哟!怎么可能?!!我可是把最坏情况都优化到了调用spfa一次呢!!!为啥还是TLE呢5555~~~
于是,弱鸡因此发现了一个重大发现!弱鸡去网上看了看别人用spfa过的代码,看看之后觉得,嗯?难道是杭电oj故意***难我?于是一股脑在交了3次。于是。。。结果大家懂的。
唉,弱鸡只好细心比对代码,一个个比对一个个比对呀!发现只不过人家写的队列而弱鸡用的栈(还是写的模拟),由于还不会直接用STL的队列和栈,于是弱弱的我只好把模拟栈改成的模拟对列,结果大出我所料!!!!!!弱鸡简直是兴奋极了!!!!一个顺序的不同却直接造成了时间的巨大差异。这足以说明spfa还是具有偶然性,(并不能说明只能用队列写,有的情况是只能用栈不能用队列!)
所以以后写spfa的时候弱鸡会注意这些的,同时还得去读读上次某学长给的人品导论,要是比赛遇到了只求人品好一遍ac!
#include <iostream> #include <cstdio> #include <cstring> #include<algorithm> #define max0 999999 using namespace std; int dl[1000000],cc[1005][1005],dis[1005]; bool vis[1005]; int min0(int a,int b) { return a>b?b:a; } void spfa(int s,int n) { int r=0,l=0; memset(dl,0,sizeof(dl)); memset(vis,1,sizeof(vis)); for(int i=1;i<=n;i++) dis[i]=max0; dis[s]=0; dl[r++]=s; while(l<r) { int x=dl[l]; vis[x]=1; for(int i=1;i<=n;i++) { if(cc[x][i]!=max0) { if(dis[i]>dis[x]+cc[x][i]) { dis[i]=dis[x]+cc[x][i]; if(vis[i]) { dl[r++]=i; vis[i]=0; } } } } l++; } } int main() { int n,m,s; while(~scanf("%d%d%d",&n,&m,&s)) { int a,b,c; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j)cc[i][j]= max0;else cc[i][j]=0; for(int i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&c); if(c<cc[b][a]) cc[b][a]=c; } spfa(s,n); int q,sum=max0;scanf("%d",&q); while(q--) { int p;scanf("%d",&p); sum=min0(sum,dis[p]); } if(sum==max0)printf("-1\n"); else printf("%d\n",sum); } return 0; }