Bellman-Ford模板
转载链接:http://blog.csdn.net/niushuai666/article/details/6791765
Dijkstra算法是处理单源最短路径的有效算法,但它局限于边的权值非负的情况,若图中出现权值为负的边,Dijkstra算法就会失效,求出的最短路径就可能是错的。
这时候,就需要使用其他的算法来求解最短路径,Bellman-Ford算法就是其中最常用的一个。该算法由美国数学家理查德•贝尔曼(Richard Bellman, 动态规划的提出者)和小莱斯特•福特(Lester Ford)发明。
适用条件&范围:
单源最短路径(从源点s到其它所有顶点v);
有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图);
边权可正可负(如有负权回路输出错误提示);
差分约束系统;
Bellman-Ford算法的流程如下:
给定图G(V, E)(其中V、E分别为图G的顶点集与边集),源点s,数组Distant[i]记录从源点s到顶点i的路径长度,初始化数组Distant[n]为, Distant[s]为0;
以下操作循环执行至多n-1次,n为顶点数:
对于每一条边e(u, v),如果Distant[u] + w(u, v) < Distant[v],则另Distant[v] = Distant[u]+w(u, v)。w(u, v)为边e(u,v)的权值;
若上述操作没有对Distant进行更新,说明最短路径已经查找完毕,或者部分点不可达,跳出循环。否则执行下次循环;
为了检测图中是否存在负环路,即权值之和小于0的环路。对于每一条边e(u, v),如果存在Distant[u] + w(u, v) < Distant[v]的边,则图中存在负环路,即是说改图无法求出单源最短路径。否则数组Distant[n]中记录的就是源点s到各顶点的最短路径长度。
可知,Bellman-Ford算法寻找单源最短路径的时间复杂度为O(V*E).
Bellman-Ford算法可以大致分为三个部分
第一,初始化所有点。每一个点保存一个值,表示从原点到达这个点的距离,将原点的值设为0,其它的点的值设为无穷大(表示不可达)。
第二,进行循环,循环下标为从1到n-1(n等于图中点的个数)。在循环内部,遍历所有的边,进行松弛计算。
第三,遍历途中所有的边(edge(u,v)),判断是否存在这样情况:
d(v) > d (u) + w(u,v)
则返回false,表示途中存在从源点可达的权为负的回路。
之所以需要第三部分的原因,是因为,如果存在从源点可达的权为负的回路。则 应为无法收敛而导致不能求出最短路径。
测试代码如下:(下面为有向图的Bellman-Ford算法。。。。。)
- #include<iostream>
- #include<cstdio>
- using namespace std;
- #define MAX 0x3f3f3f3f
- #define N 1010
- int nodenum, edgenum, original; //点,边,起点
- typedef struct Edge //边
- {
- int u, v;
- int cost;
- }Edge;
- Edge edge[N];
- int dis[N], pre[N];
- bool Bellman_Ford()
- {
- for(int i = 1; i <= nodenum; ++i) //初始化
- dis[i] = (i == original ? 0 : MAX);
- for(int i = 1; i <= nodenum - 1; ++i)
- for(int j = 1; j <= edgenum; ++j)
- if(dis[edge[j].v] > dis[edge[j].u] + edge[j].cost) //松弛(顺序一定不能反~)
- {
- dis[edge[j].v] = dis[edge[j].u] + edge[j].cost;
- pre[edge[j].v] = edge[j].u;
- }
- bool flag = 1; //判断是否含有负权回路
- for(int i = 1; i <= edgenum; ++i)
- if(dis[edge[i].v] > dis[edge[i].u] + edge[i].cost)
- {
- flag = 0;
- break;
- }
- return flag;
- }
- void print_path(int root) //打印最短路的路径(反向)
- {
- while(root != pre[root]) //前驱
- {
- printf("%d-->", root);
- root = pre[root];
- }
- if(root == pre[root])
- printf("%d\n", root);
- }
- int main()
- {
- scanf("%d%d%d", &nodenum, &edgenum, &original);
- pre[original] = original;
- for(int i = 1; i <= edgenum; ++i)
- {
- scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].cost);
- }
- if(Bellman_Ford())
- for(int i = 1; i <= nodenum; ++i) //每个点最短路
- {
- printf("%d\n", dis[i]);
- printf("Path:");
- print_path(i);
- }
- else
- printf("have negative circle\n");
- return 0;
- }
Bellman-Ford模板的更多相关文章
- ACM/ICPC 之 最短路径-Bellman Ford范例(POJ1556-POJ2240)
两道Bellman Ford解最短路的范例,Bellman Ford只是一种最短路的方法,两道都可以用dijkstra, SPFA做. Bellman Ford解法是将每条边遍历一次,遍历一次所有边可 ...
- poj1860 bellman—ford队列优化 Currency Exchange
Currency Exchange Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 22123 Accepted: 799 ...
- uva 558 - Wormholes(Bellman Ford判断负环)
题目链接:558 - Wormholes 题目大意:给出n和m,表示有n个点,然后给出m条边,然后判断给出的有向图中是否存在负环. 解题思路:利用Bellman Ford算法,若进行第n次松弛时,还能 ...
- Bellman—Ford算法思想
---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G ...
- Bellman - Ford 算法解决最短路径问题
Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力 ...
- bellman ford优先队列优化简介模板
#include<iostream>#include<cstdio>#include<utility>#include<queue>#include&l ...
- Dijkstra算法与Bellman - Ford算法示例(源自网上大牛的博客)【图论】
题意:题目大意:有N个点,给出从a点到b点的距离,当然a和b是互相可以抵达的,问从1到n的最短距离 poj2387 Description Bessie is out in the field and ...
- POJ 2240 Arbitrage (Bellman Ford判正环)
Arbitrage Time Limit: 1000MS Memory Limit: 65536K Total Submissions:27167 Accepted: 11440 Descri ...
- poj1860 兑换货币(bellman ford判断正环)
传送门:点击打开链接 题目大意:一个城市有n种货币,m个货币交换点,你有v的钱,每个交换点只能交换两种货币,(A换B或者B换A),每一次交换都有独特的汇率和手续费,问你存不存在一种换法使原来的钱更多. ...
- ACM/ICPC 之 Bellman Ford练习题(ZOJ1791(POJ1613))
这道题稍复杂一些,需要掌握字符串输入的处理+限制了可以行走的时间. ZOJ1791(POJ1613)-Cave Raider //限制行走时间的最短路 //POJ1613-ZOJ1791 //Time ...
随机推荐
- 20145301 赵嘉鑫 《网络对抗》Exp5 MSF基础应用
20145301 赵嘉鑫 <网络对抗>Exp5 MSF基础应用 一 实验链接 渗透实验一:MS08_067渗透实验 渗透实验二:MS14_064渗透实验 (首用) 渗透实验三:Adobe ...
- WideCharToMultiByte和MultiByteToWideChar函数的用法(转载)
出处:http://www.cnblogs.com/gakusei/articles/1585211.html 为了支持Unicode编码,需要多字节与宽字节之间的相互转换.这两个系统函数在使用时需要 ...
- jsp拾遗
JSP九大内置对象,七大动作,三大指令 https://blog.csdn.net/qq_34337272/article/details/64310849 JSP页面的静态包含和动态包含 https ...
- 基础dp 记录
51nod 1134 最长递增子序列 #include<iostream> #include<cstdio> #include<cstring> #include& ...
- hdu 6180 Schedule
Schedule Problem Description There are N schedules, the i-th schedule has start time si and end time ...
- 51NOD 1081 子段求和
1081 子段求和 给出一个长度为N的数组,进行Q次查询,查询从第i个元素开始长度为l的子段所有元素之和. 例如,1 3 7 9 -1,查询第2个元素开始长度为3的子段和,1 {3 7 9} ...
- js精度问题
JavaScript数字精度丢失问题总结 现象 原因 计算机的二进制实现和位数限制有些数无法有限表示.就像一些无理数不能有限表示,如 圆周率 3.1415926...,1.3333... 等.JS 遵 ...
- codeforces 251 div2 C. Devu and Partitioning of the Array 模拟
C. Devu and Partitioning of the Array time limit per test 1 second memory limit per test 256 megabyt ...
- 在采用vue-cli Post Get
需要依赖插件 vue-resource npm install vue-resource --save https://cn.vuejs.org/v2/cookbook/using-axios-to- ...
- Python 以指定宽度格式化输出
当对一组数据输出的时候,我们有时需要输出以指定宽度,来使数据更清晰.这时我们可以用format来进行约束 mat = "{:20}\t{:28}\t{:32}" print(mat ...