利用SPFA算法求最短路

该算法由Bellman-Ford算法演变过来,首先介绍一下Bellman-Ford算法

最短路最多经过n-1个点,可以用n-1轮松弛操作来得到

for(int i=0;i<n;i++)
    d[i]=INF;
d[0]=0;
for(int k=0;k<n-1;k++)
for(int i=0;i<m;i++)  //检查每条边 
{
    int x=u[i];
    int y=v[i];
    if(d[x]<INF)
        d[y]=min(d[y],d[x]+w[i]);
} 

当然这个算法我没有实际应用过,而是一直在用它的优化算法,利用队列代替前面的循环检查

SPFA最坏时间复杂度仍然为O(nm),但是有人分析其时间复杂度为O(km),k为每个点入队次数,正确性未知

SPFA和Bellman-Ford都可以检测负环但是只有后者可以输出负环

下面给出邻接表实现的SPFA算法,可以求出单源最短路。

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 const int maxn=10005;
 5 const int maxm=500005;
 6 const int INF=0x7fffffff;
 7 //
 8 int n,m,s;
 9 //
10 int g[maxn];
11 struct point
12 {
13     int t,w,next;
14 }e[maxm];
15 int d[maxn];
16 //
17 int tot=0;
18 void addedge(int a,int b,int c)
19 {
20     tot++;
21     e[tot].t=b;
22     e[tot].w=c;
23     e[tot].next=g[a];
24     g[a]=tot;
25 }
26 //
27 int q[maxn];
28 bool v[maxn];
29 void spfa(int x0)
30 {
31     for(int i=1;i<=n;i++)
32     d[i]=(i==x0?0:INF);
33     int h=0,t=1;
34     q[t]=x0;
35     while(h!=t)
36     {
37         h=h%maxn+1;
38         int x=q[h];
39         v[x]=false;
40         for(int tmp=g[x];tmp;tmp=e[tmp].next)
41         {
42             if(d[e[tmp].t]>d[x]+e[tmp].w)
43             {
44                 d[e[tmp].t]=d[x]+e[tmp].w;
45                 if(!v[e[tmp].t])
46                 {
47                     v[e[tmp].t]=true;
48                     t=t%maxn+1;
49                     q[t]=e[tmp].t;
50                 }
51             }
52         }
53     }
54 }
55 int main()
56 {
57     cin>>n>>m>>s;
58     for(int i=1;i<=m;i++)
59     {
60         int x,y,z;
61         cin>>x>>y>>z;
62         addedge(x,y,z);
63     }
64     spfa(s);
65     for(int i=1;i<=n;i++)
66         cout<<d[i]<<" ";
67     return 0;
68 }

猜你喜欢

转载自www.cnblogs.com/aininot260/p/9272894.html