最短路(spfa)
http://acm.hdu.edu.cn/showproblem.php?pid=2544
最短路
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 41979 Accepted Submission(s): 18360
Problem Description
在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?
Input
输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。
输入保证至少存在1条商店到赛场的路线。
Output
对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
Sample Input
2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0
Sample Output
3
2
Source
联系spfa模板
复杂度O(ke);
spfa是 bellman-Ford的优化,其用队列解决问题,可以判定负环,每次从队列中出栈一个元素,用这个元素更新其他的点到初始点的距离,被更新的点获得了新的更新别的点的潜力,所以将其也加入到队列中,每次更新dis数组
如果是用数组来储存队列的时候因为每次i和top 指针都是向后会浪费很多的空间,所以可以使用循环队列,只用开N这么大的数即可,top每次%N ,当i!=top的时候说明队列不空,下面的代码将循环队列的内容给出了特别的标注
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define N 250 6 #define M 10005 7 #define INF 0x1fffffff 8 struct Edge{ 9 int to; 10 int w ; 11 int next; 12 }edge[M]; 13 int Enct; 14 int head[N]; 15 void init() 16 { 17 Enct = 0; 18 memset(head,-1,sizeof(head)); 19 } 20 void add(int from , int to,int w) 21 { 22 edge[Enct].to= to; 23 edge[Enct].w = w; 24 edge[Enct].next = head[from]; 25 head[from] = Enct++; 26 edge[Enct].to= from; 27 edge[Enct].w = w; 28 edge[Enct].next = head[to]; 29 head[to] = Enct++; 30 } 31 int que[N]; 32 bool inq[N]; 33 int top; 34 int dis[N]; 35 int n; 36 int SPFA() 37 { 38 memset(inq,0,sizeof(inq)); 39 for(int i =0 ;i <= n ;i++) 40 dis[i] = INF; 41 top = 0; 42 dis[1] = 0; 43 que[top++] = 1; 44 inq[1]=true; 45 for(int i = 0;i != top ;i = i+1%N)//队列不为空,注意i和top不是同时循环到下一次的 46 { 47 int u = que[i]; 48 inq[u]=false; 49 for(int j = head[u] ; j!=-1 ;j = edge[j].next) 50 { 51 Edge e = edge[j]; 52 if(dis[e.to]>dis[u]+e.w) 53 { 54 dis[e.to] = dis[u]+e.w; 55 if(inq[e.to]==false) 56 { 57 que[top++] = e.to; 58 top %= N;//循环队列 59 inq[e.to] = true; 60 } 61 } 62 } 63 } 64 return dis[n]; 65 } 66 int main() 67 { 68 int m ; 69 while(~scanf("%d %d",&n,&m) && (n!=0||m!=0)) 70 { 71 init(); 72 int s , t , w; 73 for(int i = 0 ;i < m ;i++) 74 { 75 scanf("%d%d%d",&s,&t,&w); 76 add(s,t,w); 77 } 78 printf("%d\n",SPFA()); 79 } 80 return 0; 81 }