最短路径算法2——Bellman-Ford与SPFA算法
Bellman-Ford算法:
只能计算单源最短路径,时间复杂度为O(nm)n是顶点数,m是边数。
其实这个算法很简单,代码实现也很简单,大致和Floyed差不多吧。
循环n-1次,每次循环遍历所有边,必然会有一些边连接着蓝点与白点。因此每次都能用所有的白点去修改所有的蓝点。所以这个算法只是理论模拟了蓝点白点,并没有真正实现。
Bellman-Ford代码:
1 #include<cstdio> 2 #include<iostream> 3 #define N 42000 4 using namespace std; 5 int n,m,p,q,a[N],b[N],c[N],d[N]; 6 int main(){ 7 scanf("%d%d%d%d",&n,&m,&p,&q); 8 for(int i=1;i<=m;++i) 9 scanf("%d%d%d",&a[i],&b[i],&c[i]); 10 for(int i=1;i<=n;++i) 11 d[i]=42000000; 12 d[p]=0; 13 for(int i=1;i<n;++i) 14 for(int j=1;j<=m;++j) 15 d[b[j]]=min(d[b[j]],d[a[j]]+c[j]); 16 printf("%d",d[q]); 17 return 0; 18 }
SPFA算法:
SPFA算法是Bellman-Ford算法的一种队列实现,减少了不必要的冗杂计算,时间复杂度为O(km)m是边数,k是常数,平均值为2.
基本思路是初始将起点加入队列,每次从队列取出一个元素,并对所有和它相连的节点进行修改,若修改某个点成功,将这给点入队,直到队列为空。
SPFA代码:
1 #include<queue> 2 #include<cstdio> 3 #define N 42000 4 using namespace std; 5 queue<int>h; 6 int next[N],to[N],dis[N],num,head[N],n,m,p,q,a,b,c,d[N],u,boo[N]; 7 void add(int false_from,int false_to,int false_dis){ 8 next[++num]=head[false_from]; 9 to[num]=false_to; 10 dis[num]=false_dis; 11 head[false_from]=num; 12 } 13 int main(){ 14 scanf("%d%d%d%d",&n,&m,&p,&q); 15 for(int i=1;i<=m;++i){ 16 scanf("%d%d%d",&a,&b,&c); 17 add(a,b,c); 18 add(b,a,c); 19 } 20 for(int i=1;i<=n;++i) 21 d[i]=42000000; 22 d[p]=0; 23 h.push(p); 24 do{ 25 u=h.front(); 26 h.pop(); 27 boo[u]=0; 28 for(int v=head[u];v;v=next[v]) 29 if(d[u]+dis[v]<d[to[v]]){ 30 d[to[v]]=d[u]+dis[v]; 31 if(!boo[to[v]]){ 32 h.push(to[v]); 33 boo[to[v]]=1; 34 } 35 } 36 }while(!h.empty()); 37 printf("%d",d[q]); 38 return 0; 39 }