一、算法概述

Bellman-Ford算法解决的是一般情况下的单源最短路径问题。所谓单源最短路径问题:给定一个图G=(V,E),我们希望找到从给定源结点s属于V到每个结点v属于V的最短路径。单源最短路径问题可以用来解决许多其他问题,其中包括下面几个最短路径的变体问题。包括单目的最短路径问题、单结点最短路径问题、所有结点对最短路径问题,这里不详细介绍。回到bellman-Ford,在这里,边的权重可以为负值。给定带权重的有向图G=(V,E)和权重函数W
: E-->R,Bellman-Ford算法返回一个布尔值,以表明是否存在一个从源点可以到达的权重为负值的环路。如果存在这样的环路,算法将告诉我们不存在解决方案。如果没有这种环路存在,算法将给出最短路径和它们的权重。边的权值可以为负数、实现简单,缺点是时间复杂度过高,高达O(VE)。但算法可以进行若干种优化,提高了效率。

自然语言描述

对有向图,用贝尔曼-福特算法求以为源点的最短路径的过程:

  • 建立,表示目前已知源点到各个节点的最短距离,起始值,其余皆为
  • 建立表示某节点路径上的父节点,起始值皆为NULL。
  • ,比较,并将小的赋给,如果修改了(松弛操作)
  • 重复以上操作
  • 再重复操作一次,如,则此图存在负权环。

    伪代码表示

BellmanFord(G,s)
for i = 0 to n-1 do
dist[i]= ∞
Pred[i]= 0
dist[s]=0
for k = 1 to n-1 do
foreach do
if do


foreach do
if do
return "No Shortest Path"
return dist[]

二、原理

为什么说最短路径不存在负环呢?

如果图G包含从s可以达到的权重为负值的环路,则最短路径权重无定义。从s到该环路上的任意结点的路径都不可能是最短路径,因为我们只要沿着任何“最短”路径再遍历一次权重为负值的环路,则总是可以找到一条权重更小的路径。如果从结点s到结点v的某条路径上存在权重为负值的环路,我们定义s到v的最短路径等于负无穷。

松弛操作

它的原理是对图进行V-1次松弛操作,得到所有可能的最短路径。对于一条边(u,v)的松弛过程为:首先测试一下是否可以对源点s到v的最短路径进行改善。测试的方法是,将从结点s到结点u之间的最短路径距离加上结点u与v之间的权重,并与当前的s到v的最短路径估计进行比较,如果前者更小,则对v.d(源点s到v的最短路径) 和v.π(前驱结点)进行更新。

每次松弛操作实际上是对相邻节点的访问,第次松弛操作保证了所有深度为n的路径最短。由于图的最短路径最长不会经过超过条边,所以可知贝尔曼-福特算法所得为最短路径。

   负边权操作

与迪科斯彻算法不同的是,迪科斯彻算法的基本操作“拓展”是在深度上寻路,用于有向无环图的最短路径算法对每条边仅松弛一次。Bellman-Ford“松弛”操作则是在广度上寻路,这就确定了贝尔曼-福特算法可以对负边进行操作而不会影响结果。

负权环判定

因为负权环可以无限制的降低总花费,所以如果发现第次操作仍可降低花销,就一定存在负权环。

三、队列优化——SPFA

求单源最短路的SPFA算法的全称是:Shortest Path Faster Algorithm。松弛操作必定只会发生在最短路径前导节点松弛成功过的节点上,用一个队列记录松弛过的节点,可以避免了冗余计算。复杂度可以降低到O(kE),k是个比较小的系数(并且在绝大多数的图中,k<=2,然而在一些精心构造的图中可能会上升到很高)

       实现方法:建立一个队列,初始时里只有起始点,再建立一个表格记录起始点到所有点的最短路径(该表格的初始值要赋为极大值,该点到他本身的路径赋为0)。然后执行松弛操作,用队列里有的点去刷新起始点到所有点的最短路,如果刷新成功且被刷新点不在队列中则把该点加入到队列最后。重复执行直到队列为空
      判断有无负环:如果某个点进入队列的次数超过N次则存在负环 (存在负环则无最短路径,如果有负环则会无限松弛,而一个带n个点的图至多松弛n-1次



参考:算法导论、http://zh.wikipedia.org/zh-cn/%E8%B4%9D%E5%B0%94%E6%9B%BC-%E7%A6%8F%E7%89%B9%E7%AE%97%E6%B3%95#.E6.9D.BE.E5.BC.9B

版权声明:本文为博主原创文章,未经博主允许不得转载。

Bellman-Ford算法及其队列优化(SPFA)的更多相关文章

  1. Bellman—Ford算法思想

    ---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G ...

  2. Bellman - Ford 算法解决最短路径问题

    Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力 ...

  3. 基于bellman-ford算法使用队列优化的spfa求最短路O(m),最坏O(n*m)

    acwing851-spfa求最短路 #include<iostream> #include<cstring> #include<algorithm> #inclu ...

  4. Dijkstra算法与Bellman - Ford算法示例(源自网上大牛的博客)【图论】

    题意:题目大意:有N个点,给出从a点到b点的距离,当然a和b是互相可以抵达的,问从1到n的最短距离 poj2387 Description Bessie is out in the field and ...

  5. 最短路径之Bellman-Ford算法的队列优化及邻接表

    参考链接:https://blog.csdn.net/qq_40626497/article/details/81139344

  6. poj1860 bellman—ford队列优化 Currency Exchange

    Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 22123   Accepted: 799 ...

  7. 关于SPFA的双端队列优化

    7.11 Update 我做题的时候发现这样写会RE 因为在使用双端队列优化SPFA的时候 在将一个点加入队列的时候,如果队列已经空了 那么一旦出现dis[Q.front()]就会RE 可以这样修改 ...

  8. SPFA(Bellman-Ford队列优化)

    原理:队列+松弛操作 将源点加入队尾,每一步读取队头顶点u,并将队头顶点u出队(记得消除标记):将与点u相连的所有点v进行松弛操作,如果能更新距离(即令d[v]变小),那么就更新,另外,如果点v没有在 ...

  9. uva 558 - Wormholes(Bellman Ford判断负环)

    题目链接:558 - Wormholes 题目大意:给出n和m,表示有n个点,然后给出m条边,然后判断给出的有向图中是否存在负环. 解题思路:利用Bellman Ford算法,若进行第n次松弛时,还能 ...

随机推荐

  1. 如何基于OM模型使用C#在程序中给SharePoint的BCS外部数据类型的字段赋值

    概述: 外部内容类型和数据,SharePoint从2010这个版本开始就对BCS提供非常强大的支持,点点鼠标就可以取代以前直接编辑XML的方式来设置SharePoint到SQL数据库的连接.非常方便地 ...

  2. iOS 字典与JSON相互转换

    iOS 字典与JSON相互转换 首先简单说一下为什么会写这种幼稚的文章. 现在的网络请求几乎都是AFN完成的,AFN也为我们写了了JSON转换字典的方法,但是不要忘记后台是一个很爱用JSON的人群,H ...

  3. KMP算法 hdu4686 Oulipo

    Problem Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, w ...

  4. ubuntu14.04安装chrome

    到https://www.google.com/chrome/browser/desktop/index.html可下载指定版本的deb文件. 32bit: wget https://dl.googl ...

  5. linux下文件压缩与解压操作

    对于刚刚接触Linux的人来说,一定会给Linux下一大堆各式各样的文件名给搞晕.别个不说,单单就压缩文件为例,我们知道在Windows下最常见的压缩文件就只有两种,一是,zip,另一个是.rap.可 ...

  6. Linux环境下Websphere重启

    一.Websphere控制台重启 1.更新class文件发布,Websphere自动重启. 2.更新web.xml发布,需要手动更新web.xml或者更新项目. web.config 缓存位置: We ...

  7. javaScript中的querySelector()与querySelectorAll()的区别

    之前,在JavaScript获取文档元素一文中,我曾介绍了获取文档元素的几种方法,最后一种方法是通过选择器获取文档元素.它的核心思想便是利用querySelector()或querySelectorA ...

  8. 【CH1602】最大异或和 trie+贪心

    题目大意:给定 N 个数,求这 N 个数中任选两个数进行异或运算,求最大的异或和是多少. 一个 int 类型的整数,可以看作一个长度为32位的字符串,异或运算不像加法,最大值不一定是由两个较大值得到. ...

  9. python时间戳转时间

    import time timestamp = 1462451334 #转换成localtime time_local = time.localtime(timestamp) #转换成新的时间格式(2 ...

  10. win8中 cmd直接以管理员权限运行

    一.组合键 WIN+X   二.锁定到任务栏,方便以后快速启动     三.控制面板->控制中心     四.更改用户账户控制设置--调到最低 好了,点击任务栏的命令提示符