最短路径算法专题3----Bellman-Ford
这个算法也是求单源最短路径用的,但是这个算法可以解决Dijkstra不能解决的负权边问题。
算法要点:
1、用dis存放源点到任意一点的距离。
2、用三个数组存放输入的点到点以及点到点的距离,x【i】,y【i】,x_y_dis【i】其中表示x【i】到y【i】的距离为x_y_dis【i】。
3、循环边数,比较dis【y【i】】和dis【x【i】】+ x_y_dis【i】,然后更新dis【y【i】】,意思和Dijkstra很像,就是源点到y点的距离如果大于源点到x的距离加上x到y的距离就更新。//注意这里是y在dis前面,因为y是目的点,x到y是有方向的。
4、最外面循环点数,注意要循环N-1个点,因为N个点最短距离的最大边数不能超过N-1。
5、设置两个标识去标志,已经不能松弛了,尽早跳出循环,图有负权环路(只是进行优化处理,在模型中就不写出了)
算法模型:
for(点数-1)
{
for(边数)
{
if(dis【y【i】】> dis【x【i】】+ x_y_dis【i】)
dis【y【i】】= dis【x【i】】+ x_y_dis【i】)
}
}
算法的核心:
最外面循环第一次意思是,找到源点到目的地,经过一条边也就是进过输入时的纯x_y_dis距离比现在的距离小,那么进行松弛。
第二次循环就是,经过两条边之后的优化,因为经过一条边的最小值已经在第一次循环保存进dis中了,所以是经过两条边。
这也就很好解释为啥是N-1次循环,因为如果N个点,有N条边那一定肯定其中有回路了。
也就很好解释了为什么标识能过提前跳出循环,因为如M边的循环不能松弛的话,那么加上M+1条边就不可能再松弛了。
#include<cstdio>
#include<cstdlib>
#include<iostream> using namespace std;
/*Bellman-Ford*/ int dis[];
int x[];
int y[];
int x_y_dis[];
const int MAX = ;//定义一个最大值,距离不会超过这个 int main()
{
int i,j,q;//循环变量
int n,m;
int check=;//当这个标记为1时代表重复了,已经不能松弛了,尽早跳出循环
int flag=;//当这个标记为1时代表这个图有负权环路
cin>>n>>m;//输入N*N的图,和M条边对应的值 for (i = ; i <= n; i++)//初始化dis距离
dis[i] = MAX; for (i = ; i <= m; i++)
{
cin>>x[i]>>y[i]>>x_y_dis[i];//输入x到y的距离为z
} dis[] = ;//自己到自己肯定是0 for (q = ; q <= n-; q++)//注意最外面的循环是循环的总的点数减一个,因为两个点最多包含N-1条边
{
check = ;//如果循环结束还是1则证明没有松弛任何一个值
for (i = ; i <= m; i++)
{
if(dis[y[i]] > dis[x[i]] + x_y_dis[i])
{
dis[y[i]] = dis[x[i]] + x_y_dis[i];
check = ;
}
}
if(check == )//如果不能松弛任何一个值,那么跳出循环
break;
} if(check == )//只有最后一次循环还是有松弛的情况下才有可能出现无限松弛的负权环路
{
check=;
//判断是否有负权环路
for (i = ; i <= m; i++)
{
if(dis[y[i]] > dis[x[i]] + x_y_dis[i])
{
dis[y[i]] = dis[x[i]] + x_y_dis[i];
check = ;
}
if(check == )
break;
}
if(check == )
{
cout<<"这个图有负权回路,没有最短路径"<<endl;
}
} if(check != )//经过上面的判断只有如果没有负权回路,就输出
{
for (i = ; i <= n; i++)
{
cout<<dis[i]<<" ";
}
cout<<endl;
}
else
return ; } /* 6 9
1 2 1
1 3 12
2 3 9
2 4 3
3 5 5
4 3 4
4 5 13
4 6 15
5 6 4
Result:0 1 8 4 13 17 5 5
2 3 2
1 2 -3
1 5 5
4 5 2
3 4 3
Result:0 -3 -1 2 4
*/
最后想提的是,这个算法的时间复杂度是O(NM)也就是当M特别多的时候(题目故意恶心你)需要进一步的优化处理,我之后再实现。
但是这个算法的优点就是能解决负边权的问题。
和Dijkstra相比,Dijkstra是在两个点之间加一个点,利用点去循环更新一个距离之后就认为这个距离已经是最优解了,后面利用最优解去不断取出后面点的最优解。而Bellman-Ford是循环输入的边,让边的不断增加去更新距离,所以当边不断的增加,距离也就更新了,无论你距离的正负。
最短路径算法专题3----Bellman-Ford的更多相关文章
- 最短路径算法专题2----Dijkstra
这个算法适用于求单源最短路径,从一点出发,到其余个点的最短路径. 算法要点: 1.用二维数组存放点到点的距离-----不能相互到达的点用MAX代替距离 2.用dis数组存放源点到任意其他一点的距离-- ...
- Bellman—Ford算法思想
---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G ...
- Bellman - Ford 算法解决最短路径问题
Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力 ...
- ACM/ICPC 之 最短路径-Bellman Ford范例(POJ1556-POJ2240)
两道Bellman Ford解最短路的范例,Bellman Ford只是一种最短路的方法,两道都可以用dijkstra, SPFA做. Bellman Ford解法是将每条边遍历一次,遍历一次所有边可 ...
- Johnson 全源最短路径算法
解决单源最短路径问题(Single Source Shortest Paths Problem)的算法包括: Dijkstra 单源最短路径算法:时间复杂度为 O(E + VlogV),要求权值非负: ...
- Floyd-Warshall 全源最短路径算法
Floyd-Warshall 算法采用动态规划方案来解决在一个有向图 G = (V, E) 上每对顶点间的最短路径问题,即全源最短路径问题(All-Pairs Shortest Paths Probl ...
- Bellman-Ford 单源最短路径算法
Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Leste ...
- 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次松弛时,还能 ...
随机推荐
- 第二题 已知有十六支男子足球队参加2008 北京奥运会。写一个程序,把这16 支球队随机分为4 个组。采用List集合和随机数 2008 北京奥运会男足参赛国家: 科特迪瓦,阿根廷,澳大利亚,塞尔维亚,荷兰,尼日利亚、日本,美国,中国,新西 兰,巴西,比利时,韩国,喀麦隆,洪都拉斯,意大利
import java.util.ArrayList; import java.util.List; import java.util.Random; public class List1 { pub ...
- css font简写规则
是不是在很很多网站的公共样式中会看到这样的代码?font: 12px/150% Arial, Verdana, "\5b8b\4f53";意思为:字体大小/行高 字体族 " ...
- 本篇内容简要介绍BASE64、MD5、SHA、HMAC几种加密算法。
BASE64编码算法不算是真正的加密算法. MD5.SHA.HMAC这三种加密算法,可谓是非可逆加密,就是不可解密的加密方法,我们称之为单向加密算法.我们通常只把他们作为加密的基础.单纯的以上 ...
- UVALive 2520 Holedox Moving(BFS+状态压缩)
这个题目在比赛的时候我们是没有做出来的,但是听到他们说进制哈希的时候,感觉真的是挺高端的,于是赛后开始补题,本着我的习惯在看题解之前自己再试着写一遍,我当时存储状态的方法是string + map,我 ...
- [原]innerText与innerHTML区别
window.onload = function () { document.getElementById('btn1').onclick = function () { ...
- OutputDebugString输出调试信息到debugtrack
OutPutDebugString()函数的输出则可以用DebugView捕获(DebugView也可以捕获TRACE宏的输出)eg: OutPutDebugString("输出第一调试信息 ...
- 导入Excel后绑定GridView实例
http://blog.csdn.net/loveheronly/article/details/6715552 项目中经常用到导入导出的例子,前面做了导出的例子,现在把导入Excel的数据的例子也把 ...
- 十三章:使用WEB字体
1.WEB字体可以使用一系列文件类型,下面介绍三种字体类型: (1)内嵌OpenType (2)TrueType和OpenType台式机使用的标准字体文件类型 (3)WEB开放字体格式. 2.构造子集 ...
- [Lua]Lua高级教程Metatables
什么是Metatable metatable是Lua中的重要概念,每一个table都可以加上metatable,以改变相应的table的行为. Metatables举例 -- 声明一个正常的关系变量 ...
- Storm官方帮助手册翻译(上)
Storm作为当前最流行的实时计算框架,自Twitter将其开源后就一直备受关注.由于其具有先天的稳定性以及便捷性,目前被许多大公司所采用,国外像雅虎.雅虎日本.Twitter.OOYALA.Spot ...