1、算法概述算法
Bellman-Ford算法解决的是通常状况下的单源最短路径问题。所谓单源最短路径问题:给定一个图G=(V,E),咱们但愿找到从给定源结点s属于V到每一个结点v属于V的最短路径。单源最短路径问题能够用来解决许多其余问题,其中包括下面几个最短路径的变体问题。包括单目的最短路径问题、单结点最短路径问题、全部结点对最短路径问题,这里不详细介绍。回到bellman-Ford,在这里,边的权重能够为负值。给定带权重的有向图G=(V,E)和权重函数W : E-->R,Bellman-Ford算法返回一个布尔值,以代表是否存在一个从源点能够到达的权重为负值的环路。若是存在这样的环路,算法将告诉咱们不存在解决方案。若是没有这种环路存在,算法将给出最短路径和它们的权重。边的权值能够为负数、实现简单,缺点是时间复杂度太高,高达O(VE)。但算法能够进行若干种优化,提升了效率。函数
天然语言描述测试
对有向图,用贝尔曼-福特算法求以
为源点的最短路径的过程:优化
伪代码表示
spa
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[]
2、原理htm
为何说最短路径不存在负环呢?队列
若是图G包含从s能够达到的权重为负值的环路,则最短路径权重无定义。从s到该环路上的任意结点的路径都不多是最短路径,由于咱们只要沿着任何“最短”路径再遍历一次权重为负值的环路,则老是能够找到一条权重更小的路径。若是从结点s到结点v的某条路径上存在权重为负值的环路,咱们定义s到v的最短路径等于负无穷。
ip
松弛操做get
它的原理是对图进行V-1次松弛操做,获得全部可能的最短路径。对于一条边(u,v)的松弛过程为:首先测试一下是否能够对源点s到v的最短路径进行改善。测试的方法是,将从结点s到结点u之间的最短路径距离加上结点u与v之间的权重,并与当前的s到v的最短路径估计进行比较,若是前者更小,则对v.d(源点s到v的最短路径) 和v.π(前驱结点)进行更新。
it
每次松弛操做其实是对相邻节点的访问,第次松弛操做保证了全部深度为n的路径最短。因为图的最短路径最长不会通过超过
条边,因此可知贝尔曼-福特算法所得为最短路径。
负边权操做
与迪科斯彻算法不一样的是,迪科斯彻算法的基本操做“拓展”是在深度上寻路,用于有向无环图的最短路径算法对每条边仅松弛一次。Bellman-Ford“松弛”操做则是在广度上寻路,这就肯定了贝尔曼-福特算法能够对负边进行操做而不会影响结果。
负权环断定
由于负权环能够无限制的下降总花费,因此若是发现第次操做仍可下降花销,就必定存在负权环。
3、队列优化——SPFA
求单源最短路的SPFA算法的全称是:Shortest Path Faster Algorithm。松弛操做一定只会发生在最短路径前导节点松弛成功过的节点上,用一个队列记录松弛过的节点,能够避免了冗余计算。复杂度能够下降到O(kE),k是个比较小的系数(而且在绝大多数的图中,k<=2,然而在一些精心构造的图中可能会上升到很高)