SPFA 每次看到“更好”的边缘时都会将新节点放入队列中,以最小化您的总距离,这只是 Bellman-Ford 的更好修剪。Bellman-Ford 算法已经证明非负加权循环的最大值为|V| - 1 条边。
因此,要检查一个循环是否为负权重,您只需要检查您是否至少使用了|V| SPFA 运行期间的边缘。换句话说,检查你是否至少访问过同一个节点|V| 次。
这是附加的伪代码:
procedure SPFA(G, s)
for each vertex v ≠ s in V(G)
d(v) := ∞
visits(v) := 0
d(s) := 0
push s into Q
while Q is not empty
u := pop Q
visits(u) := visits(u) + 1 // increment visit count
if visits(u) < |V| then // relaxation step
for each edge (u, v) in E(G)
if d(u) + w(u, v) < d(v) then
d(v) := d(u) + w(u, v)
if v is not in Q then
push v into Q
但是,请注意,这不会得到所有属于负权重循环的节点。要获取属于负权重循环的所有节点,请执行 DFS 或 BFS 以标记所有可从u到达的节点,其中visits( u ) = |V| .
这是最终修改后的伪代码:
procedure DFS(G, u, visited)
if visited(u) = false then
visited(u) := true
for each edge (u, v) in E(G)
DFS(G, v, visited)
procedure SPFA(G, s)
for each vertex v ≠ s in V(G)
d(v) := ∞
visits(v) := 0
d(s) := 0
push s into Q
while Q is not empty
u := pop Q
visits(u) := visits(u) + 1 // increment visit count
if visits(u) < |V| then // relaxation step
for each edge (u, v) in E(G)
if d(u) + w(u, v) < d(v) then
d(v) := d(u) + w(u, v)
if v is not in Q then
push v into Q
for each vertex u in V(G)
visited(u) := false
for each vertex u in V(G), where visits(u) = |V|
DFS(G, u, visited)
for each vertex u in V(G), where visited(u) = true
d(u) := -∞