Bellman-Ford算法(求最短路径,并检测负权回路)
来源:互联网 发布:中国网民规模季度数据 编辑:程序博客网 时间:2024/06/06 01:10
Bellman - ford(贝尔曼-福特)算法是求含负权图的单源最短路径的一种算法,效率较低,代码难度较小。其原理为连续进行松弛,在每次松弛时把每条边都更新一下,若在n-1次松弛后还能更新,则说明图中有负环,因此无法得出结果,否则就完成。
算法时间复杂度O(VE)。因为算法简单,适用范围又广,虽然复杂度稍高,仍不失为一个很实用的算法。(百度百科)
网上关于这个算法的讲解文章比较多,总结可分为三个步骤。
1.初始化所有点。dist[]数组保存每个点的值,表示从原点到达这个点的距离,将原点的值设为0,其它的点的值设为无穷大(表示不可达)。
2.进行n-1次循环,循环下标为从1到n-1(n等于图中点的个数)。
在循环内部,遍历所有的边,进行松弛计算。
(关于松弛操作不懂的,可以看下这个博客http://www.wutianqi.com/?p=1912)
3.遍历途中所有的边,判断是否存在dist[edge[j].v]>dist[edge[j].u]+edge[j].w
存在则返回false,表示途中存在从源点可达的权为负的回路。
以上图为例,初始,A到B的距离为5,B到C的距离为2,C到A的距离为9;
0+5=5<20,所以B的值变为5,这个过程的意义是,找到了一条通向B点更短的路线,且该路线是先经过点A,然后通过权重为5的边,到达点B。依此遍历。
图中红色为第一次循环后各点新的值,紫色为第二次循环后各点新的值,由于只有三个点,也就是第二部分循环两次结束,进入第三部分。
此时仍然满足-4+5=1<3,即存在负权回路,flag=false;
注意,此算法的返回值为true或false;
贴代码:
#include <stdio.h>#include <stack>using namespace std;#define MAX 10000//假设权值最大不超过10000struct Edge{ int u;//边的起始顶点 int v;//边终止顶点 int w;//权};Edge edge[1000];int dist[100];int path[100];int vn;//顶点数int en;//边数int source;//源点bool BellmanFord(){ //初始化 for(int i=0;i<vn;i++) dist[i]=(i==source)? 0:MAX; //n-1次循环 for(int i=1;i<=vn-1;i++) for(int j=0;j<en;j++){ if(dist[edge[j].v]>dist[edge[j].u]+edge[j].w) { dist[edge[j].v]=dist[edge[j].u]+edge[j].w; path[edge[j].v]=edge[j].u; }}bool flag=true;//第n次循环判断负权回路for(int i=0;i<en;i++){ if(dist[edge[i].v]>dist[edge[i].u]+edge[i].w) flag=false; break;}return flag;}void print()//利用栈的特性进行存储,方便输出{ for(int i=0;i<vn;i++) { if(i!=source) { int p=i; stack<int> s; printf("顶点%d到顶点%d的最短路径是:",source,p); while(source!=p) { s.push(p); p=path[p]; } printf("%d",source); while(!s.empty()) { printf("--%d",s.top()); s.pop(); } printf(" 最短路径长度是:%d\n",dist[i]); } }}int main(){ printf("请输入图的顶点数 边数 源点:"); scanf("%d %d %d",&vn,&en,&source); printf("请输入%d条边的信息(起点,终点,权值):",en); for(int i=0;i<en;i++) scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); if(BellmanFord()) print(); elseprintf("Sorry,it have negative circle!\n"); return 0;}
- Bellman-Ford算法(求最短路径,并检测负权回路)
- Bellman-Ford算法判断负权回路
- Bellman-Ford算法,解决负权回路。
- 图--单源最短路径 -Bellman Ford 算法(可以存在负权边的情况和负权回路)算法导论p362
- [ACM] POJ 3259 Wormholes (bellman-ford最短路径,判断是否存在负权回路)
- POJ-3259 Wormholes(负权回路[Bellman-Ford])
- 图论;单源最短路径;拓扑排序+松弛(有向无回路);Bellman-Ford(回路,负权回路);Dijkstra(无负权,可回路);可以用最小堆实现算法的优化;
- 图论;单源最短路径;拓扑排序+松弛(有向无回路);Bellman-Ford(回路,负权回路);Dijkstra(无负权,可回路);可以用最小堆实现算法的优化;
- 图论;单源最短路径;拓扑排序+松弛(有向无回路);Bellman-Ford(回路,负权回路)Dijkstra(无负权,可回路);可以用最小堆实现算法的优化;
- poj 3259 bellman-ford算法 判断是否存在负权回路
- PKU 3259 Wormholes - 判断负权回路 Bellman-Ford
- POJ 3259 Wormholes(判断负权回路|SPFA||Bellman-Ford)
- poj 3259 bellman-ford判断是否存在负权回路
- bellman-ford算法——最短路问题,判断是否存在负权回路或正权回路
- bellman-ford算法——最短路问题,判断是否存在负权回路或正权回路
- 最短路径基本介绍(3)--Bellman-Ford算法(单源最短路径算法,可求负权)
- POJ 1860 Currency Exchange Bellman-Ford算法求单源最短路径并判断是否有正权回路
- 【算法】Bellman-Ford算法(单源最短路径问题)(判断负圈)
- 历年北京理工大学复试专业综合题
- lucene查询之 多条件查询 BooleanQuery 可以组合查询条件。及代码示例
- CSAPP SHLAB
- 【免费赠书】Python中文社区光棍节活动!
- Go基础编程:工程管理
- Bellman-Ford算法(求最短路径,并检测负权回路)
- git权威指南总结四:进度保存与恢复
- 【JavaScript】什么时候不能用箭头函数
- lucene查询之 queryparser查询;及代码示例;代码实现;及查询语法解析
- JAVA创建抽象类
- 二叉树的实现
- Manacher算法
- 团队天梯赛L1-017. 到底有多二
- lucene查询之 MulitFieldQueryParser 可以指定多个默认搜索域;及代码示例;代码实现