原来一直没去学spfa,感觉只一个Dij已经很够用了,昨天翻了一下最短路,如果路径中存在负权的话,Dij也只能素手无策,这时spfa就大显身手了。。
实现过程:
我们用数组d记录每个结点的最短路径估计值,而且用邻接表来存储图G。我们采取的方法是松弛:
设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,
并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,
且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止。
这道题很明显的最短路,分别用两个版本写了下。
spfa:
View Code
1 # include<stdio.h>
2 # include<string.h>
3 # include<queue>
4 using namespace std;
5 # define N 1005
6 # define M 2005
7 # define PI 0xfffffff
8 struct node{
9 int from,to,next,val;
10 }edge[M*2];
11 int head[N],tol,visit[N],dis[N],n,m;
12 void add(int a,int b,int c)
13 {
14 edge[tol].from=a;edge[tol].to=b;edge[tol].val=c;edge[tol].next=head[a];head[a]=tol++;
15 }
16 void spfa()
17 {
18 int u,cur,i;
19 queue<int >q;
20 q.push(1);
21 dis[1]=0;
22 visit[1]=1;
23 while(!q.empty())
24 {
25 cur=q.front();
26 visit[cur]=0;
27 q.pop();
28 for(i=head[cur];i!=-1;i=edge[i].next)
29 {
30 u=edge[i].to;
31 if(edge[i].val+dis[cur]<dis[u])
32 {
33 dis[u]=edge[i].val+dis[cur];
34 if(visit[u]==0) {visit[u]=1;q.push(u);}
35 }
36 }
37 }
38 return;
39 }
40 int main()
41 {
42 int i,a,b,c;
43 scanf("%d%d",&m,&n);
44 memset(head,-1,sizeof(head));
45 tol=0;
46 for(i=1;i<=m;i++)
47 {
48 scanf("%d%d%d",&a,&b,&c);
49 add(a,b,c);
50 add(b,a,c);
51 }
52 memset(visit,0,sizeof(visit));
53 for(i=1;i<=n;i++)
54 dis[i]=PI;
55 spfa();
56 printf("%d\n",dis[n]);
57 return 0;
58 }
Dij:
View Code
1 # include<stdio.h>
2 # include<string.h>
3 # define N 1005
4 # define M 2005
5 # define PI 0xfffffff
6 int adj[N][N],low[N],visit[N];
7 int main()
8 {
9 int i,n,m,min,index,index1,a,b,c;
10 scanf("%d%d",&m,&n);
11 memset(adj,-1,sizeof(adj));
12 memset(visit,0,sizeof(visit));
13 for(i=1;i<=m;i++)
14 {
15 scanf("%d%d%d",&a,&b,&c);
16 if(adj[a][b]==-1 ||adj[a][b]>c)
17 adj[a][b]=adj[b][a]=c;
18 }
19 for(i=1;i<=n;i++)
20 low[i]=PI;
21 index=1;
22 low[1]=0;
23 while(1)
24 {
25 visit[index]=1;
26 min=PI;
27 for(i=1;i<=n;i++)
28 {
29 if(visit[i]==1) continue;
30 if(low[i]==PI && adj[i][index]==-1) continue;
31 if(adj[i][index]!=-1)
32 {
33 if(adj[i][index]+low[index]<low[i]) low[i]=adj[i][index]+low[index];
34 }
35 if(low[i]<min) {min=low[i];index1=i;}
36 }
37 index=index1;
38 if(index==n) break;
39 }
40 printf("%d\n",low[n]);
41 return 0;
42 }