bellman ford 算法 判断是否存在负环

微信小程序实战项目——点餐系统        程序员11月书讯,评论得书啦        Get IT技能知识库,50个领域一键直达
关闭
 

bellman ford 算法

 11148人阅读 评论(0) 收藏 举报
 分类:

[cpp] view plaincopy
  1. <span style="font-family: Arial, Helvetica, sans-serif;"><span style="border-bottom-width:1px; border-bottom-style:dashed; border-bottom-color:rgb(201,201,201)"><a href="http://www.wutianqi.com/?p=1890" target="_blank" style="background-color:transparent; border-width:0px 0px 1px; border-bottom-style:dashed; border-bottom-color:rgb(201,201,201); margin:0px; padding:0px; vertical-align:baseline; color:rgb(0,102,204); text-decoration:none; outline:none">Dijkstra算法</a></span></span><a href="http://wutianqi-blog.b0.upaiyun.com/2011/01/2.png" style="font-family: Arial, Helvetica, sans-serif; background-color: transparent; border-width: 0px 0px 1px; border-bottom-style: dashed; border-bottom-color: rgb(201, 201, 201); margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204); text-decoration: none; outline: none;"></a><a href="http://wutianqi-blog.b0.upaiyun.com/2011/01/4.png" style="font-family: Arial, Helvetica, sans-serif; background-color: transparent; border-width: 0px 0px 1px; border-bottom-style: dashed; border-bottom-color: rgb(201, 201, 201); margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204); text-decoration: none; outline: none;"></a><a href="http://wutianqi-blog.b0.upaiyun.com/2011/01/bellman_ford.jpg" style="font-family: Arial, Helvetica, sans-serif; background-color: transparent; border-width: 0px 0px 1px; border-bottom-style: dashed; border-bottom-color: rgb(201, 201, 201); margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204); text-decoration: none; outline: none;"></a><span style="font-family: Arial, Helvetica, sans-serif;">是处理单源最短路径的有效算法,但它局限于边的权值非负的情况,若图中出现权值为负的边,Dijkstra算法就会失效,求出的最短路径就可能是错的。这时候,就需要使用其他的算法来求解最短路径,</span><a href="http://www.wutianqi.com/?p=1912" target="_blank" style="font-family: Arial, Helvetica, sans-serif; background-color: transparent; border-width: 0px 0px 1px; border-bottom-style: dashed; border-bottom-color: rgb(201, 201, 201); margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204); text-decoration: none; outline: none;">Bellman-Ford算法</a><span style="font-family: Arial, Helvetica, sans-serif;">就是其中最常用的一个。该算法由美国数学家理查德•贝尔曼(Richard Bellman, 动态规划的提出者)和小莱斯特•福特(Lester Ford)发明。Bellman-Ford算法的流程如下:</span>  
给定图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).

首先介绍一下松弛计算。如下图:


 

松弛计算之前,点B的值是8,但是点A的值加上边上的权重2,得到5,比点B的值(8)小,所以,点B的值减小为5。这个过程的意义是,找到了一条通向B点更短的路线,且该路线是先经过点A,然后通过权重为2的边,到达点B。
当然,如果出现一下情况


 

则不会修改点B的值,因为3+4>6。
 
Bellman-Ford算法可以大致分为三个部分
第一,初始化所有点。每一个点保存一个值,表示从原点到达这个点的距离,将原点的值设为0,其它的点的值设为无穷大(表示不可达)。
第二,进行循环,循环下标为从1到n-1(n等于图中点的个数)。在循环内部,遍历所有的边,进行松弛计算。
第三,遍历途中所有的边(edge(u,v)),判断是否存在这样情况:
d(v) > d (u) + w(u,v)
则返回false,表示途中存在从源点可达的权为负的回路。
 
之所以需要第三部分的原因,是因为,如果存在从源点可达的权为负的回路。则 应为无法收敛而导致不能求出最短路径。
考虑如下的图:
 

经过第一次遍历后,点B的值变为5,点C的值变为8,这时,注意权重为-10的边,这条边的存在,导致点A的值变为-2。(8+ -10=-2)
 
 

第二次遍历后,点B的值变为3,点C变为6,点A变为-4。正是因为有一条负边在回路中,导致每次遍历后,各个点的值不断变小。
 
在回过来看一下bellman-ford算法的第三部分,遍历所有边,检查是否存在d(v) > d (u) + w(u,v)。因为第二部分循环的次数是定长的,所以如果存在无法收敛的情况,则肯定能够在第三部分中检查出来。比如
 

此时,点A的值为-2,点B的值为5,边AB的权重为5,5 > -2 + 5. 检查出来这条边没有收敛。
 
所以,Bellman-Ford算法可以解决图中有权为负数的边的单源最短路径问。

个人感觉算法导论讲解很不错,把这一章贴出来和大家分享:

24.1 The Bellman-Ford algorithm

The Bellman-Ford algorithm solves the single-source shortest-paths problem in the general case in which edge weights may be negative. Given a weighted, directed graph G = (VE) with source s and weight function w : E → R, the Bellman-Ford algorithm returns a boolean value indicating whether or not there is a negative-weight cycle that is reachable from the source. If there is such a cycle, the algorithm indicates that no solution exists. If there is no such cycle, the algorithm produces the shortest paths and their weights.

The algorithm uses relaxation, progressively decreasing an estimate d[v] on the weight of a shortest path from the source s to each vertex v ∈ V until it achieves the actual shortest-path weight δ(sv). The algorithm returns TRUE if and only if the graph contains no negative-weight cycles that are reachable from the source.

BELLMAN-FORD(G, w, s)
1  INITIALIZE-SINGLE-SOURCE(G, s)
2  for i1 to |V[G]| - 1
3       do for each edge (u, v) ∈ E[G]
4              do RELAX(u, v, w)
5  for each edge (u, v) ∈ E[G]
6       do if d[v] > d[u] + w(u, v)
7             then return FALSE
8  return TRUE

Figure 24.4 shows the execution of the Bellman-Ford algorithm on a graph with 5 vertices. After initializing the d and π values of all vertices in line 1, the algorithm makes |V| – 1 passes over the edges of the graph. Each pass is one iteration of the for loop of lines 2-4 and consists of relaxing each edge of the graph once. Figures 24.4(b)-(e) show the state of the algorithm after each of the four passes over the edges. After making |V|- 1 passes, lines 5-8 check for a negative-weight cycle and return the appropriate boolean value. (We’ll see a little later why this check works.)

(单击图片可以放大)

Figure 24.4: The execution of the Bellman-Ford algorithm. The source is vertex s. The d values are shown within the vertices, and shaded edges indicate predecessor values: if edge (u, v) is shaded, then π[v] = u. In this particular example, each pass relaxes the edges in the order (t, x), (t, y), (t, z), (x, t), (y, x), (y, z), (z, x), (z, s), (s, t), (s, y). (a) The situation just before the first pass over the edges. (b)-(e) The situation after each successive pass over the edges. The d and π values in part (e) are the final values. The Bellman-Ford algorithm returns TRUE in this example.

The Bellman-Ford algorithm runs in time O(V E), since the initialization in line 1 takes Θ(V) time, each of the |V| – 1 passes over the edges in lines 2-4 takes Θ(E) time, and the for loop of lines 5-7 takes O(E) time.

以下是Bellman-Ford代码:

[cpp] view plaincopy
  1. #include <iostream>  
  2. using namespace std;  
  3. const int maxnum = 100;  
  4. const int maxint = 99999;  
  5.   
  6. // 边,  
  7. typedef struct Edge{  
  8.     int u, v;    // 起点,重点  
  9.     int weight;  // 边的权值  
  10. }Edge;  
  11.   
  12. Edge edge[maxnum];     // 保存边的值  
  13. int  dist[maxnum];     // 结点到源点最小距离  
  14.   
  15. int nodenum, edgenum, source;    // 结点数,边数,源点  
  16.   
  17. // 初始化图  
  18. void init()  
  19. {  
  20.     // 输入结点数,边数,源点  
  21.     cin >> nodenum >> edgenum >> source;  
  22.     for(int i=1; i<=nodenum; ++i)  
  23.         dist[i] = maxint;  
  24.     dist[source] = 0;  
  25.     for(int i=1; i<=edgenum; ++i)  
  26.     {  
  27.         cin >> edge[i].u >> edge[i].v >> edge[i].weight;  
  28.         if(edge[i].u == source)          //注意这里设置初始情况  
  29.             dist[edge[i].v] = edge[i].weight;  
  30.     }  
  31. }  
  32.   
  33. // 松弛计算  
  34. void relax(int u, int v, int weight)  
  35. {  
  36.     if(dist[v] > dist[u] + weight)  
  37.         dist[v] = dist[u] + weight;  
  38. }  
  39.   
  40. bool Bellman_Ford()  
  41. {  
  42.     for(int i=1; i<=nodenum-1; ++i)  
  43.         for(int j=1; j<=edgenum; ++j)  
  44.             relax(edge[j].u, edge[j].v, edge[j].weight);  
  45.     bool flag = 1;  
  46.     // 判断是否有负环路  
  47.     for(int i=1; i<=edgenum; ++i)  
  48.         if(dist[edge[i].v] > dist[edge[i].u] + edge[i].weight)  
  49.         {  
  50.             flag = 0;  
  51.             break;  
  52.         }  
  53.     return flag;  
  54. }  
  55. int main()  
  56. {  
  57.     //freopen("input3.txt", "r", stdin);  
  58.     init();  
  59.     if(Bellman_Ford())  
  60.         for(int i = 1 ;i <= nodenum; i++)  
  61.             cout << dist[i] << endl;  
  62.     return 0;  
  63. }  


补充:


考虑:为什么要循环V-1次?
答:因为最短路径肯定是个简单路径,不可能包含回路的,
如果包含回路,且回路的权值和为正的,那么去掉这个回路,可以得到更短的路径
如果回路的权值是负的,那么肯定没有解了

图有n个点,又不能有回路
所以最短路径最多n-1边

又因为每次循环,至少relax一边
所以最多n-1次就行了

3
0

我的同类文章

  • Uva 10891 sum 游戏 (及其变型) ;动态规划2013-05-31
  • 二分图匹配算法总结2013-05-25
  • 求最大权二分匹配的KM算法2013-05-25
  • ACM进阶指南2013-05-25
  • 匈牙利算法 求解 完美的牛栏2013-05-24
  • 欧拉回路2013-05-28
  • 二分图带权匹配 KM算法与费用流模型建立2013-05-25
  • 著名的北邮ACM推荐50题2013-05-25
  • HDOJ---2036 过山车[匈牙利算法]2013-05-24
  • hdu 1466计算直线的交点数2013-05-03
更多文章

参考知识库

img

算法与数据结构知识库

猜你在找
《C语言/C++学习指南》加密解密篇(安全相关算法)
C语言系列之 递归算法示例与 Windows 趣味小项目
C语言系列之 字符串相关算法
C语言系列之 字符串压缩算法与结构体初探
模板匹配的字符识别(OCR)算法原理
图最短路径Bellman-Ford算法
BellmanFord算法实现解决存在负边情况下单源最短路径问题
最短路模板Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA
最短路径算法Bellman-Ford贝尔曼
poj Wormholes 最短路 spfa Bellman-Ford 算法 邻接表实现
查看评论

  暂无评论

发表评论
  • 用 户 名:
  • hang__xiu2016acm
  • 评论内容:
  • 插入代码
  •   
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
核心技术类目
全部主题 Hadoop AWS 移动游戏 Java Android iOS Swift 智能硬件 Docker OpenStack VPN Spark ERP IE10Eclipse CRM JavaScript 数据库 Ubuntu NFC WAP jQuery BI HTML5 Spring Apache .NET API HTML SDK IISFedora XML LBS Unity Splashtop UML components Windows Mobile Rails QEMU KDE Cassandra CloudStack FTCcoremail OPhone CouchBase 云计算 iOS6 Rackspace Web App SpringSide Maemo Compuware 大数据 aptech PerlTornado Ruby Hibernate ThinkPHP HBase Pure Solr Angular Cloud Foundry Redis Scala Django Bootstrap
  • 个人资料
  •  
    Flyer_
     
    1
    • 访问:75445次
    • 积分:1071
    • 等级: 
    • 排名:千里之外
    • 原创:24篇
    • 转载:47篇
    • 译文:0篇
    • 评论:10条
  • 文章分类
  • unix环境高级编程(18)
  • unix网络编程(4)
  • tcp/ip(4)
  • unix/linux(10)
  • ACM(12)
  • 笔试(13)
  • 面试(8)
  • PAT(4)
  • 30天自制操作系统(1)
  • 前端(4)
  • HTML&CSS(3)
  • ML(7)
  • 文章存档
    • 2016年10月(1)
    • 2016年08月(1)
    • 2016年07月(6)
    • 2015年07月(3)
    • 2015年03月(1)
      展开
  • 阅读排行
  • bellman ford 算法(11142)
  • 网络爬虫c实现(9636)
  • 2014阿里巴巴9月14北京校园招聘笔试及参考答案(3983)
  • 两道操作系统题目---多道程序(3511)
  • TCP/IP网络编程之四书五经(2704)
  • 2012九月十月腾讯,网易游戏,百度最新校园招聘笔试题(2619)
  • Linux进程地址空间与虚拟内存(2337)
  • PAT 1010. 一元多项式求导 (25)(2186)
  • PAT 1009. 说反话 (20)(2011)
  • 腾讯后台开发面试题(1764)
  • 评论排行
  • 2014阿里巴巴9月14北京校园招聘笔试及参考答案(3)
  • 网络爬虫c实现(2)
  • 进程与线程的一个简单解释(2)
  • 两道操作系统题目---多道程序(1)
  • LINUX/UNIX 文件状态标志的 与或非 操作(1)
  • 编程之美_单链表面试题_结合3.4_3.6(1)
  • 2014找工作总结-机会往往留给有准备的人(1)
  • 著名的北邮ACM推荐50题(0)
  • ACM进阶指南(0)
  • 匈牙利算法 求解 完美的牛栏(0)
  • 推荐文章
    • * RxJava详解,由浅入深
    • * 倍升工作效率的小策略
    • * Android热修复框架AndFix原理解析及使用
    • * “区块链”究竟是什么鬼
    • * 架构设计:系统存储-MySQL主从方案业务连接透明化(中)
  • 最新评论
  • 两道操作系统题目---多道程序

    Daringoo: 第二题,腾讯给的标准答案是A。在csdn上有自动的测试,我看到了显示的答案。但是不知怎么得来的。

  • ssd8ex1

    Tiger_Humour: 楼主你好,请问18到25行代码里的;这一段代码是如何确定uri.indexOf('/',8)+1的。...

  • 网络爬虫c实现

    Echo_Wei1991: 正在写这个的大作业,谢谢啦~太赞

  • 进程与线程的一个简单解释

    qwe8642511: 很好,但是为什么那个锁上在了门外面。。。。。。出不来了~

  • 2014阿里巴巴9月14北京校园招聘笔试及参考答案

    weidahou227: @xiaor186:大哥你能好好算算在评论吗,字母有重复的

  • 2014阿里巴巴9月14北京校园招聘笔试及参考答案

    xiaor186: 哎,哥啊,看来这参考答案也真的是只能是参考下而已。第一个的答案用脚趾数都不可能是D吧,应该是A

  • 编程之美_单链表面试题_结合3.4_3.6

    岁月小龙: 没有实现代码啊

  • 网络爬虫c实现

    岁月小龙: xialai慢慢看

  • 进程与线程的一个简单解释

    岁月小龙: 这个图文并茂,真是太好了

  • 2014找工作总结-机会往往留给有准备的人

    Deebug: 谢谢博主的建议。+1

  • 链接
  • Hackbuteer1
    结构之法 算法之道

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/509091.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[转载]文本特征TFIDF权重计算及文本向量空间VSM表示

https://blog.csdn.net/Fighting_No1/article/details/51000066

TFIDF java实现

代码模板&#xff1a; jar包下载&#xff1a;https://download.csdn.net/download/dreamzuora/10853842 /*** */ package TFIDF;import java.util.Arrays; import java.util.List;/*** author weijie* 作用&#xff1a;用来计算词项对于一个文档集或一个语料库中的一份文件的重…

KDTree算法

原理&#xff1a; 1.https://www.cnblogs.com/porco/p/4464414.html&#xff08;里面代码不好修改&#xff0c;不建议直接利用&#xff09; 2.https://www.cnblogs.com/zfyouxi/p/4795584.html 实例&#xff1a;可以用来求最短距离的点&#xff0c;例如&#xff1a;根据经纬度求…

【java机器学习】决策树算法

参考文章&#xff1a;https://blog.csdn.net/qq_38773180/article/details/79188510 java代码&#xff1a; package decisionTree; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.FileNotFoundException; i…

C++ vector用法

C vector用法 在c中&#xff0c;vector是一个十分有用的容器&#xff0c;下面对这个容器做一下总结。 1 基本操作 (1)头文件#include<vector>. (2)创建vector对象&#xff0c;vector<int> vec; (3)尾部插入数字&#xff1a;vec.push_back(a); (4)使用下标访问元素&…

【java机器学习】词向量在贝叶斯中的概念

向量&#xff1a; 在数学中&#xff0c;向量&#xff08;也称为欧几里得向量、几何向量、矢量&#xff09;&#xff0c;指具有大小&#xff08;magnitude&#xff09;和方向的量 词向量&#xff1a; 词向量&#xff08;Word embedding&#xff09;&#xff0c;又叫Word嵌入式自…

【java机器学习】贝叶斯分类

参考文章&#xff1a;https://blog.csdn.net/qq_24369113/article/details/53291867#commentsedit

【java机器学习】支持向量机之拉格朗日乘子法解释

什么是拉格朗日乘子法 按照维基百科的定义&#xff0c;拉格朗日乘数法是一种寻找多元函数在其变量受到一个或多个条件的约束时的极值的方法。用数学式子表达为&#xff1a; 简单理解就是&#xff0c;我们要在满足 这个等式的前提下&#xff0c;求 函数的最小值&#xff08;最大…

字典树(Trie树)

字典树(Trie树)字典树&#xff0c;又称单词查找树&#xff0c;Trie树&#xff0c;是一种树形结构&#xff0c;典型应用是用于统计&#xff0c;排序和保存大量的字符串&#xff0c;所以经常被搜索引擎系统用于文本词频统计。它的优点是&#xff1a;利用字符串的公共前缀来节约存…

【java机器学习】svm入门十讲

博客&#xff1a;http://www.blogjava.net/zhenandaci/archive/2009/03/06/258288.html

Java解析json出现双引号变成转义字符解决办法

Java中&#xff1a;利用StringEscapeUtils.unescapeHtml4强转 String newJson StringEscapeUtils.unescapeHtml4(jsonStr);

棋盘问题 dfs

棋盘问题Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 38265 Accepted: 18742 Description 在一个给定形状的棋盘&#xff08;形状可能是不规则的&#xff09;上面摆放棋子&#xff0c;棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列…

JedisConnectionException: java.Net.SocketTimeoutException: Read timed

jedis操作&#xff1a;https://blog.csdn.net/shuaiOKshuai/article/details/23266091 jedisPool操作&#xff1a;https://blog.csdn.net/gongxinju/article/details/53909239

jedisPool的使用

遇到的问题&#xff1a; 一开始做项目一直用的是jedis对象连接&#xff0c;今天发现自己上线的项目抛出了异常:JedisConnectionException: java.Net.SocketTimeoutException: Read timed和和java.lang.ClassCastException: [B cannot be cast to java.util.List。 异常解释&…

ssdb教程

常见问题解答&#xff1a;http://ssdb.io/docs/zh_cn/faq.html https://www.w3xue.com/server/ssdb/ssdb-comlist.html http://ssdb.io/docs/zh_cn/commands/index.html https://www.w3cschool.cn/ssdb/xd2leud8.html

java ssdb 操作link遍历map的两种方式

方法一&#xff1a;不推荐使用&#xff0c;只会返回map中的key Link link ssdb.link; resp link.request("qpush", "q", "a");for(int i1; i<resp.raw.size(); i2){ String s new String(resp.raw.get(i)); System.out.println(s); }方法…

FileOutputStream为false时候注意的问题

今天写代码时候发现&#xff0c;new FileOutputStream(new File(“test.txt”), false)时候test.txt文件内容会清空&#xff0c;记录一下&#xff01;

java文件重命名有趣实验

Testpublic void filetest() throws Exception {//判断文件会写入到哪个文件内File file new File("test.txt");file.renameTo(new File("test1.txt"));FileOutputStream out new FileOutputStream(file);out.write("ok".getBytes());out.clos…

网络流之最大流算法(EdmondsKarp)

网络流之最大流算法&#xff08;EdmondsKarp&#xff09; 标签&#xff1a; 网络流算法EdmondsKarp流量最大流2014-03-11 18:05 34795人阅读 评论(12) 收藏 举报分类&#xff1a;图论~~网络流&#xff08;26&#xff09; 版权声明&#xff1a;本文为博主原创文章&#xff0c;未…

java文件流操作注意

今天做了一个测试&#xff1a; Testpublic void fileOut() throws Exception {FileOutputStream out new FileOutputStream(new File("test.txt"), false);out.write("1".getBytes());out.write("2".getBytes());File file new File("tes…