Archipelago

Lec 14全源最短路径与 Johnson 算法

讲义完成更新于 2026-09-16

Lec 14 全源最短路径与 Johnson 算法

资料依据:课程视频与 transcript · Lecture notes

TL;DR

  • 全源最短路径(APSP)可以对每个源点运行一次单源算法,但负边使我们不能直接使用 Dijkstra。
  • Johnson 算法用一次 Bellman–Ford 计算势函数,把每条边重标为非负,同时保持所有路径的相对优劣。
  • 重标后可从每个顶点运行 Dijkstra;结合二叉堆时总成本为 O(∣V∣∣E∣log⁡∣V∣)O(|V||E|\log |V|),适合稀疏图。

复习 SSSP 算法

我们主要学写了 4 个解决 SSSP 问题的算法,要解决最短路径问题,首先要定义和构造与你的问题相关的图,然后用其中一种算法来解决你的问题。一般来说,你会尽量用最快的方法,Bellman-Ford 可以应用到任何加权图问题,但它是最慢的一个,因此我们会优选其他方法。

全源最短路径与 Johnson 算法图示 1

我们针对单源最短路径(SSSP)问题介绍了这些算法,但在此过程中,我们还展示了如何使用这些算法来解决其他问题。例如,我们可以使用全量深度优先搜索(Full-DFS)或全量广度优先搜索(Full-BFS)来计算图中的连通分量,使用深度优先搜索(DFS)对有向无环图(DAG)中的顶点进行拓扑排序,并使用 Bellman-Ford 算法检测负权重环。

全源最短路径 APSP

All-Pairs Shortest Paths(APSP)问题

  • 输入:加权有向图 G=(V, E),加权函数w:E→Zw: E\rightarrow \mathbb{Z}
  • 输出:返回所有的u,v∈V的δ(u,v)u, v \in V 的 \delta(u, v), 如果 G 存在负权重环则中止(因为对于任何一个δ(u,v)=−∞\delta(u, v) = -\infty)。由此可以推断出,输出空间O(∣V∣2)O(|V|^2),因为需要知道每对顶点的加权最短路径
  • 应用: 对于了解整个网络很有用,比如传输、电路 layout、供应链管理等
  • 仅仅是用一个 SSSP 算法执行|V|次的效果也是挺好的,因为输出大小为O(∣V∣2)O(|V|^2)
    • 当权值为正且受限于 O(|E|+|V|)时, 用 BFS 的时间复杂度是|V|·O(|V|+|E|)
    • 当图是 DAG 时,用 DAG 松弛的时间复杂度是|V|·O(|V|+|E|)
    • 当权重非负且图为无向图时,用 Dijkstra 算法的时间复杂度为|V|·O(|V|log|V|+|E|)
    • 对于一般情况用 Bellman-Ford 算法的时间复杂度为|V|·O(|V|·|E|)

方法

  • 思路: 在保持最短路径性质的同时使得所有边权重非负。
  • 也就是说, 将图 G 重新加权到图 G',使得在 G 中的最短路径在 G'中也是最短路径,并且 G'中没有负权重。
    • 如果没有负权重边,那么只需要运行|V|次 Dijkstra 算法就可以解决 APSP 问题。
    • 为什么我们不需要考虑无向图?
      • 只需要检查每个边,如果有负权重,就代表有负权重环。线性时间即可
  • 断言: 可以在 O(|V|(|V|+|E|))时间内从 G'中的距离计算出 G 中的距离
    • 对于每个s∈Vs \in V,计算最短路径树的距离,时间复杂度为 O(|V| + |E|)
    • 这也是 G 中最短路径树,所以在计算距离的同时通过 DFS 遍历树
    • 需要 O(|V|(|V|+|E|))时间(比运行|V|次 Dijkstra 算法的时间少)
  • 但是,如何使 G' 具有非负边权重呢?这甚至可能吗?
  • 断言:如果 G 包含负权重环,则这是不可能的
  • 证明:如果没有负权重,最短路径是简单的,但如果有负权重环的最短路径是无限的,不是简单路径。这样是矛盾。

是权重变非负

给定一个具有负权重但没有负权重环的图 G,我们能在保留最短路径的同时使边权重非负吗?

  • 思路 1: 将 G 中最小权重的负值加到每条边上!所有权重都变成非负的! :)

    • 这样做无法保留最短路径,这样会偏向与遍历更少边的路径,(因为它给每条边都加了一个补偿值,路径越长,则更改后路径更长,不公平!)
  • 思路 2:给定顶点 v, 将 h 加到所有出边上,并从所有入边上减去 h

  • 断言 1: 最短路径在上述重新加权下得以保留

    证明:

    • 以 v 为起点的每条路径的权重变化为 h
    • 以 v 为终点的每条路径的权重变化为 −h
    • 经过 v 的路径的权重(局部)不变
  • 这是一个非常通用且很有用的技巧,在保留最短路径性质的前提下转换图形!甚至可以对多个顶点起作用

  • 定义一个势函数v:V→Zv: V \rightarrow \mathbb{Z},将每个顶点v∈Vv \in V 映射到一个势函数 h(v)

  • 构造图 G',与 G 相同,但边(u,v)∈E(u, v) \in E的权重为w′(u,v)=w(u,v)+h(u)−h(v)w'(u,v) = w(u,v) + h(u) - h(v)

  • 断言 2: 在 G 中的最短路径在 G’中也是最短路径

    证明

    • G 中路径π=(v0,...,vk)\pi = (v_0, ..., v_k)的权重w(π)=∑i=1kw(vi−1,vi)w(\pi) = \sum^k_{i=1}w(v_{i-1}, v_i)
    • 在 G'中π\pi的权重为∑i=1k(w(vi−1,vi)+h(vi−1)−h(vi))=w(π)+h(v0)−h(vk)\sum^k_{i=1}(w(v_{i-1}, v_i)+ h(v_{i-1}) - h(v_i) )= w(\pi) + h(v_0) - h(v_k)
      • 每个内部顶点 i 都有正负相抵的 h(vi)h(v_i)
    • 从v0v_0到vkv_k的每条路径的权重变化相同
    • 因此,任何最短路径仍然是最短路径

  • 我们能否找到这样的势函数,使得 G'没有负权边?
  • 即,能否存在一个 h 使得对于每个(u,v)∈E(u, v) \in E,都有w(u,v)+h(u)−h(v)≥0w(u, v) + h(u) - h(v) \ge 0
    • 将这个条件重新排列为h(v)≤h(u)+w(u,v)h(v) \le h(u) + w(u, v),看起来像是三角不等式!
  • 思路:如果将h(v)设置为某个路径的δ(s,v)h(v)设置为某个路径的\delta(s, v)且 δ(s,v)\delta(s, v)有限的,则条件将会满足
    • 但是图可能是不连通的,所以可能不存在这样的顶点 s
  • 新办法: 添加一个新顶点 s, 并向每个v∈Vv\in V添加一个权重为 0 的有向边,即添加新顶点 s 指向图中所有的顶点的边。
  • 对于所有的v∈V,δ(s,v)≤0v\in V, \delta(s, v) \le 0,因为存在权重为 0 的路径。
  • 断言: 如果δ(s,v)=−∞\delta(s, v)=-\infty对于任何v∈Vv\in V成立,那么原图中一定有负权重环
  • 证明
    • 添加 s 并不会引入新的环(s 没有入边)
    • 所以,如果重新加权后图有负权重环,则原图中也有
  • 或者, 如果对于所有v∈V,δ(s,v)v\in V, \delta(s, v)有限:
    • 根据三角不等式, 对于每个(u,v)∈E(u, v) \in E, 有w′(u,v)=w(u,v)+h(u)−h(v)≥0w'(u, v) = w(u, v) + h(u) - h(v) \ge 0
    • 重新加权后的 G‘中的新权重是非负的,同时保留了最短路径

Johnson's 算法

  • 本质上是规约算法
    • 将权值可能是正或负 APSP 问题,规约成具有相同最短路径性质,且只有非负权重边的图问题
  • 算法步骤
  1. 从 G 构造GxG_x, 通过添加顶点 x 连接到每个顶点v∈Vv\in V并设置权重为 0

  2. 计算δx(x,v),for each v∈V\delta_x(x, v), for\ each\ v \in V(使用 Bellman-Ford 算法)

  3. 有两种情况

    1. if ∃v∈V\exist v\in V, δx(x,v)=−∞\delta_x(x, v) = -\infty:
      • 中止(因为 G 中存在负权重环)
    2. else: 重新加权每条边w′(u,v)=w(u,v)+δx(x,u)−δx(x,v)w'(u, v) = w(u, v) + \delta_x(x, u) - \delta_x(x, v)以形成图 G'
  4. 对于每个u∈Vu\in V:

    • 计算 G'中所有顶点 v 的最短距离δ′(u,v)\delta'(u,v)(使用 Dijkstra 算法)

    • 对于所有v∈Vv\in V, 计算δ(u,v)=δ′(u,v)−δx(x,u)+δx(x,v)\delta(u, v) = \delta'(u, v) - \delta_x(x, u) + \delta_x(x, v)即可得到图 G 的关于顶点 u 的 SSSP 的解

正确性证明

  • 已经证明从 G 到 G' 的转换保留了最短路径
  • 剩下的归结为 Bellman-Ford 和 Dijkstra 算法的正确性
  • 从带负数权值的 APSP 到非负的 APSP 的简化

时间复杂度分析

  • 构造 GxG_x 需要 O(|V| + |E|) 时间
  • Bellman-Ford 算法需要 O(|V||E|) 时间
  • 构造 G' 需要 O(|V| + |E|) 时间
  • 运行 V 次 Dijkstra 算法需要 O(∣V∣⋅(∣V∣log⁡∣V∣+∣E∣))O(|V| \cdot (|V| \log |V| + |E|))时间
  • 计算从 G' 中的距离到 G 中的距离需要 O(|V|^2) 时间
  • 总时间复杂度为 O(∣V∣2log⁡∣V∣+∣V∣∣E∣)O(|V|^2 \log |V| + |V||E|)

我的理解

我的理解

势函数不是随意把负数变正:它使一条 sots o t 路径的总权重只增加与端点有关的常数 h(s)−h(t)h(s)-h(t)。因此同一对端点间的路径排名完全不变。