Unverified Commit aa0edb61 authored by Shuhao Zhang's avatar Shuhao Zhang Committed by GitHub
Browse files

👌 Apply suggestions from code review



Co-Authored-By: default avatarouuan <1609483441@qq.com>
parent f2550f6e
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -262,7 +262,7 @@ Johnson 和 Floyd 一样,是一种能求出无负环图上任意两点间最

任意两点间的最短路可以通过枚举起点,跑 $n$ 次 Bellman-Ford 算法解决,时间复杂度是 $O(n^2m)$ 的,也可以直接用 Floyd 算法解决,时间复杂度为 $O(n^3)$ 。

注意到堆优化的 Dijkstra 算法求单源最短路径的时间复杂度比 Bellman-Ford 更优,如果枚举起点,跑 $n$ 次 Dijkstra 算法,就可以在 $O((n^2+mn)\log m)$ 的时间复杂度内解决本问题,比上述跑 $n$ 次 Bellman-Ford 算法的时间复杂度更优秀。
注意到堆优化的 Dijkstra 算法求单源最短路径的时间复杂度比 Bellman-Ford 更优,如果枚举起点,跑 $n$ 次 Dijkstra 算法,就可以在 $O(nm\log m)$(取决于 Dijkstra 算法的实现)的时间复杂度内解决本问题,比上述跑 $n$ 次 Bellman-Ford 算法的时间复杂度更优秀,在稀疏图上也比 Floyd 算法的时间复杂度更加优秀

但 Dijkstra 算法不能正确求解带负权边的最短路,因此我们需要对原图上的边进行预处理,确保所有边的边权均非负。

@@ -290,7 +290,7 @@ Johnson 算法则通过另外一种方法来给每条边重新标注边权。

接下来以每个点为起点,跑 $n$ 轮 Dijkstra 算法即可求出任意两点间的最短路了。

容易看出,该算法的时间复杂度是 $O(nm+(n^2+nm)\log m)$ 。
一开始的 Bellman-Ford 算法并不是时间上的瓶颈,若使用 `priority_queue` 实现 Dijkstra 算法,该算法的时间复杂度是 $O(nm\log m)$ 。

### 正确性证明

@@ -318,7 +318,7 @@ Johnson 算法则通过另外一种方法来给每条边重新标注边权。

上面的新图中 $s \to t$ 的最短路的长度表达式由两部分组成,前面的边权和为原图中 $s \to t$ 的最短路,后面则是两点间的势能差。因为两点间势能的差为定值,因此原图上 $s \to t$ 的最短路与新图上 $s \to t$ 的最短路相对应。

到这里我们的正确性证明已经解决了一半——我们证明了重新标注边权后图上的最短路径仍然是原来的最短路径。接下来我们需要证明新图中所有边的边权非负,因为只有在非负权图上,Dijkstra 才能得出正确的结果。
到这里我们的正确性证明已经解决了一半——我们证明了重新标注边权后图上的最短路径仍然是原来的最短路径。接下来我们需要证明新图中所有边的边权非负,因为在非负权图上,Dijkstra 算法能够保证得出正确的结果。

根据三角形不等式,图上任意一边 $(u,v)$ 上两点满足: $h_v \leq h_u + w(u,v)$ 。这条边重新标记后的边权为 $w'(u,v)=w(u,v)+h_u-h_v \geq 0$ 。这样我们证明了新图上的边权均非负。

@@ -331,8 +331,10 @@ Johnson 算法则通过另外一种方法来给每条边重新标注边权。
| Floyd      | Bellman-Ford | Dijkstra           | Johnson                  |
| ---------- | ------------ | ------------------ | ------------------------ |
| 每对结点之间的最短路 | 单源最短路        | 单源最短路              | 每对结点之间的最短路               |
| 没有负环的图     | 任意图          | 非负权图               | 没有负环的图                   |
|  $O(N^3)$  |  $O(NM)$     |  $O((N+M)\log M)$  |  $O(NM+(N^2+NM)\log M)$  |
| 没有负环的图     | 任意图(可以判定负环是否存在) | 非负权图               | 没有负环的图                   |
|  $O(N^3)$  |  $O(NM)$     |  $O(M\log M)$  |  $O(NM\log M)$  |

注:表中的 Dijkstra 算法在计算复杂度时均用 `priority_queue` 实现。

## 输出方案