Dijkstra最短路径算法存在的一个问题是不能处理负权图(详见:经典图论算法回顾之Dijkstra算法。今天要回顾的Bellman-Ford算法(wikipedia:Bellman–Ford algorithm)可以求出有负权图的最短路径,并可以对最短路不存在(负权回路)的情况进行判断。

一、Bellman-Ford算法
不同于Dijkstra算法基于点的操作,Bellman-Ford算法则是基于边的操作。算法的核心思想是不断地对边进行松弛(Relax)操作,松弛操作定义如下:
RELAX(u, v, w)
if v.d > u.d + w(u,v)
v.d = u.d + w(u,v)
v.p = u
上述代码用于松弛边 e = ( u , v ) e = (u,v) e=(u,v)。其中, v . d v.d v.d 和 u . d u.d u.d 分别是 u , v u,v u,v 到源点的最短距离的估计值,这一值将会逐步逼近最短距离, w ( u , v ) w(u,v) w(u,v) 表示边的权重, v . p v.p v.p 表示 v v v 的潜在的最短路径上的前驱节点,用于得到最终得到某一节点的最短路径。
接下来,整个Bellman-Ford算法的伪代码如下:
BELLMAN-FORD(G,w,s)
INITIALIZE-SIGNAL-SOURCE(G,s) //初始化操作:s.d = 0, (V-s).d = ∞
for i=1 to |G.V|-1 //重复执行 |G.V| -1 次
for each edge(u,v) in G.E //对每条边进行松弛操作
RELAX(u,v,w)
for each edge(u,v) in G.E //检测是否存在边还可以继续松弛
if v.d > u.d + w(u,v) //如果存在,则有负权回路,不存在最短路径
return FALSE
return TRUE
接下来给出一个简单的示例。如图1(a)所示,我们要求源点 S S S 到其它各点的最短路径,图1(b)是初始化结果(除了源点外,其他点到源点的最短距离初始化为无穷大)。
我们指定按 ( C , D ) , ( B , D ) , ( A , C ) , ( A , B ) , ( A , D ) , ( B , C ) , ( S , B ) , ( S , A ) (C,D),(B,D),(A,C),(A,B),(A,D),(B,C),(S,B),(S,A) (C,D),(B,D),(A,C),(A,B),(A,D),(B,C),(S,B),(S,A) 的顺序依次松弛各条边。

第1轮松弛:我们发现, ( C , D ) , ( B , D ) , ( A , C ) , ( A , B ) , ( A , D ) , ( B , C ) (C,D),(B,D),(A,C),(A,B),(A,D),(B,C) (C,D),(B,


2万+

被折叠的 条评论
为什么被折叠?



