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算法的主要内容,如果未能解决你的问题,请参考以下文章

[算法学习]Bellman-Ford算法求最短路

最短路问题之Bellman-ford算法

算法笔记:图论中的单源最短路径算法——Bellman-Ford 算法

最短路之Bellman-ford算法java代码模板

Bellman-ford 单源最短路径算法

Bellman-Ford算法