Bellman-Ford算法分析
2012-08-14 11:21
246 查看
刷题的本意不在于刷了多少题,而在于通过刷题理解了多少算法,理解有多深……
Bellman-Ford算法与Dijkstra算法类似,也是用于求单源点的最短路径,与Dijkstra算法不同的是,Dijkstra算法只能用于求非负权值有向图(无向图可以看成是有向图)的单源点最短路径,而Bellman-Ford算法可以求含负权的单源点有向图的最短路径,而且Bellman-Ford算法还可以用于判断图中是否存在负权回路(负权回路即是图中存在一个环,环上的所有权值之和是负数,那么这个环就是负权回路)。但存在负权回路的图是不能够求最短路径的,因为求最短路径时会在负权回路上不断地兜圈子,所有的最短路径长度会任意小。
Bellman-Ford算法的实现很简单,但理解起来并不容易,比较复杂。原理是进行n-1次的松弛操作(n是结点个数),每次松弛操作时从边的角度出发,更新每个结点到源点的距离,使得每个结点到源点距离逐步逼近最短距离,一共要进行n-1次的松弛操作。
对于存在最短距离的有向图来说,任意一条最短路径都不可能存在正权回路,也不可能存在负权回路,因为最短路径最多只包含n-1条边,其次从源点可达的所有顶点如果存在最短路径,则这些最短路径构成以源点s为根的最短路径树,Bellman-Ford算法的松弛过程本质上就是按顶点距离源点s的层次,逐次生成这棵最短路径树的过程。
对于权值均为正的有向图(无向图转化为有向图)而言,进行完第一次松弛操作,就是找到了层次最多为1的那些树枝,即找到了与s最多有一条边相连的那些顶点的最短路径,进行完第二次的松弛操作后,就找到了层次最多为2的那些树枝,即找到了与s经过两条边的那些顶点的最短路径,………因为最短路径最多只包含n-1条边,所以进行n-1次的松弛操作就可以。每实施一次松弛操作就会有一层的顶点找到最短路径,且这些顶点的最短路径长度会保持不变,在以后的松弛操作中不会受影响。
对于有负权的无负权回路的有向图(无向图转化为有向图)则不然,进行完第i次松弛操作不一定就找到了第i层结点的最短路径,与边的顺序有关。
对于存在负权回路的图来说,是不能找到最短路径的,进行完n-1次的松弛操作后还能更新,因为寻在最短路径时会不断地在负权回路上兜圈子,所有的最短路径长度会任意小。如果不能理解可以借助三个有向图来理解:
第一个图 起点 终点 权值 1 2 -2 , 2 5 5 , 4 5 2 , 2 3 -2 , 3 4 3 , 4 2 2 , 1 4 3 ;第二个图 起点 终点 权值 1 2 -2 , 2 5 5 , 4 5 2 , 2 3
-2 , 3 4 -3 , 4 2 2 , 1 4 3 ; 第三个图 起点 终点 权值 1 2 2 , 2 5 5 , 4 5 2 , 2 3 2 , 3 4 3 , 4 2 2 , 1 4 3 ;
第一个图不含负权回路,但含负权,第二个图含负权回路,第三个图权值均为正,源点都是1,分析完这三个图,就能够很好地理解Bellman-Ford算法。
分析完这三个图就会发现Bellman-Ford算法浪费了大量的时间在做没必要的松弛操作,所以算法效率很低,需要进行优化。其中有一个小的优化就是每次松弛时设置以标志flag,初值为false,因为可能没有进行第n-1次松弛操作时,顶点到源点的距离就不能更新了(即已经找到了所有结点的路径),如果下次松弛时仍要更新到源点的最短距离,则值flag的值为true,进行完这次松弛操作后,如果flag的值为false,则直接退出,已经找到了所有结点的最短路径长度。还有其他优化方法,如SPFA等,效率很高。
Bellman-Ford算法实现代码:x[i],y[i],w[i]分别表示第i条边的起点、终点、权值,d[i]表示顶点i到源点最短距离,m条边,n个顶点。
Bellman-Ford算法与Dijkstra算法类似,也是用于求单源点的最短路径,与Dijkstra算法不同的是,Dijkstra算法只能用于求非负权值有向图(无向图可以看成是有向图)的单源点最短路径,而Bellman-Ford算法可以求含负权的单源点有向图的最短路径,而且Bellman-Ford算法还可以用于判断图中是否存在负权回路(负权回路即是图中存在一个环,环上的所有权值之和是负数,那么这个环就是负权回路)。但存在负权回路的图是不能够求最短路径的,因为求最短路径时会在负权回路上不断地兜圈子,所有的最短路径长度会任意小。
Bellman-Ford算法的实现很简单,但理解起来并不容易,比较复杂。原理是进行n-1次的松弛操作(n是结点个数),每次松弛操作时从边的角度出发,更新每个结点到源点的距离,使得每个结点到源点距离逐步逼近最短距离,一共要进行n-1次的松弛操作。
对于存在最短距离的有向图来说,任意一条最短路径都不可能存在正权回路,也不可能存在负权回路,因为最短路径最多只包含n-1条边,其次从源点可达的所有顶点如果存在最短路径,则这些最短路径构成以源点s为根的最短路径树,Bellman-Ford算法的松弛过程本质上就是按顶点距离源点s的层次,逐次生成这棵最短路径树的过程。
对于权值均为正的有向图(无向图转化为有向图)而言,进行完第一次松弛操作,就是找到了层次最多为1的那些树枝,即找到了与s最多有一条边相连的那些顶点的最短路径,进行完第二次的松弛操作后,就找到了层次最多为2的那些树枝,即找到了与s经过两条边的那些顶点的最短路径,………因为最短路径最多只包含n-1条边,所以进行n-1次的松弛操作就可以。每实施一次松弛操作就会有一层的顶点找到最短路径,且这些顶点的最短路径长度会保持不变,在以后的松弛操作中不会受影响。
对于有负权的无负权回路的有向图(无向图转化为有向图)则不然,进行完第i次松弛操作不一定就找到了第i层结点的最短路径,与边的顺序有关。
对于存在负权回路的图来说,是不能找到最短路径的,进行完n-1次的松弛操作后还能更新,因为寻在最短路径时会不断地在负权回路上兜圈子,所有的最短路径长度会任意小。如果不能理解可以借助三个有向图来理解:
第一个图 起点 终点 权值 1 2 -2 , 2 5 5 , 4 5 2 , 2 3 -2 , 3 4 3 , 4 2 2 , 1 4 3 ;第二个图 起点 终点 权值 1 2 -2 , 2 5 5 , 4 5 2 , 2 3
-2 , 3 4 -3 , 4 2 2 , 1 4 3 ; 第三个图 起点 终点 权值 1 2 2 , 2 5 5 , 4 5 2 , 2 3 2 , 3 4 3 , 4 2 2 , 1 4 3 ;
第一个图不含负权回路,但含负权,第二个图含负权回路,第三个图权值均为正,源点都是1,分析完这三个图,就能够很好地理解Bellman-Ford算法。
分析完这三个图就会发现Bellman-Ford算法浪费了大量的时间在做没必要的松弛操作,所以算法效率很低,需要进行优化。其中有一个小的优化就是每次松弛时设置以标志flag,初值为false,因为可能没有进行第n-1次松弛操作时,顶点到源点的距离就不能更新了(即已经找到了所有结点的路径),如果下次松弛时仍要更新到源点的最短距离,则值flag的值为true,进行完这次松弛操作后,如果flag的值为false,则直接退出,已经找到了所有结点的最短路径长度。还有其他优化方法,如SPFA等,效率很高。
Bellman-Ford算法实现代码:x[i],y[i],w[i]分别表示第i条边的起点、终点、权值,d[i]表示顶点i到源点最短距离,m条边,n个顶点。
for(i=1;i<n;i++) for(j=1;j<=m;j++) if(d[x[j]]+w[j]<d[y[j]]) d[y[j]]=d[x[j]]+w[j]; for(i=1;i<=m;i++) if(d[x[i]]+w[i]<d[y[i]]) return false; else return true;
相关文章推荐
- 带权最短路 Dijkstra, SPFA, Bellman-Ford, ASP, Floyd-Warshall 算法分析
- 带权最短路 Dijkstra, SPFA, Bellman-Ford, ASP, Floyd-Warshall 算法分析
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 带权最短路 Dijkstra, SPFA, Bellman-Ford, ASP, Floyd-Warshall 算法分析
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 带权最短路 Dijkstra, SPFA, Bellman-Ford, ASP, Floyd-Warshall 算法分析
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 最短路径算法—Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)
- 算法集锦(找工作前看一看)DijStla||bellman-ford||floyd
- Bellman - Ford 算法解决最短路径问题
- Bellman-Ford(贝尔曼,福特)算法——解决负权边
- 算法导论-----图论-----Bellman-ford 算法
- 求单源最短路径的算法(Bellman-Ford)
- [算法系列之二十九]Bellman-Ford最短路径算法