该算法由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 }
原文地址:https://www.cnblogs.com/aininot260/p/9272894.html
时间: 2024-11-10 23:21:01