Bellman-Ford算法
Posted mr94kevin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bellman-Ford算法相关的知识,希望对你有一定的参考价值。
Bellman-Ford算法是一种单源最短路算法,允许图中有负边权。Bellman-Ford算法的效率相对较低,但是很容易编写,也很好理解。比较流行的SPFA算法其实就是他的队列优化。Bellman-Ford算法的流程大体是这样,先将源点的最短路设置为0,将其他结点的最短路设置为inf,然后进行n-1次迭代,每次检查每条边进行松弛操作,这样就得到了其他结点的最短路。而且可以检查是否存在负环,若n次迭代仍然可以进行松弛操作,则说明存在负环。不难看出时间复杂度是O(nm)的。怎么理解Bellman-Ford算法呢?不妨想想一棵最短路径树,根是源点,叶子结点是图中其他结点,叶子结点到根节点的路径就是其他结点的最短路。虽然这棵树一开始我们并不知道什么样子,但他是客观存在的。而Bellman-Ford算法就是逐层构造这棵最短路树,假设处理到了第i层,那么第i-1层已经处理完毕,那么扫描每一条边,看是否可以松弛,一定可以由第i-1层扩展到第i层。如果把源点看做第0层,那么这棵树最多有n-1层,因此迭代n-1次一定可以得到这棵最短路树(如果存在的话),那么如果第n次仍然可以进行松弛操作,说明不存在最短路(存在负环)。
1 #include<cstdio> 2 #include<cctype> 3 #include<cstring> 4 const int inf=0x3f3f3f3f; 5 int n,m,s,d[maxn]; 6 struct edge { 7 int u,v,w; 8 edge(int u=0,int v=0,int w=-1):u(u),v(v),w(w) {} 9 } E[maxm]; 10 bool bellman() { 11 memset(d,inf,sizeof(d)); 12 d[s]=0; 13 for(int i=1;i<=n;++i) //循环检查n次,正常情况下最多迭代n-1次,第n次用于判断是否存在最短路 14 for(int i=1;i<=m;++i) { 15 int u=E[i].u,v=E[i].v,w=E[i].w; 16 if(d[v]>d[u]+w) { //松弛操作 17 if(i==n) return false; 18 else d[v]=d[u]+w; 19 } 20 } 21 return true; 22 } 23 int main() { 24 scanf("%d%d%d",&n,&m,&s); 25 int u,v,w; 26 for(int i=1;i<=m;++i) { 27 scanf("%d%d%d",&u,&v,&w); 28 E[i]=edge(u,v,w); 29 } 30 if(!bellman()) printf("Wrong!"); 31 else for(int i=1;i<=n;++i) { 32 if(i!=1) putchar(‘ ‘); 33 printf("%d",d[i]); 34 } 35 return 0; 36 }
以上是关于Bellman-Ford算法的主要内容,如果未能解决你的问题,请参考以下文章