最短路(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条商店到赛场的路线。
 


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 }

 

posted on 2015-08-06 10:28  若流芳千古  阅读(483)  评论(0编辑  收藏  举报

导航