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

fix format

parent 27008404
Loading
Loading
Loading
Loading
+13 −16
Original line number Diff line number Diff line
@@ -106,7 +106,7 @@ for (k = 1; k <= n; k++) {

三角形不等式: $dist(v) \leq dist(u) + edge\_len(u, v)$ 。

证明:反证法,如果不满足,那么可以用 $relax$ 操作来更新 $dist(v)$ 的值。
证明:反证法,如果不满足,那么可以用松弛操作来更新 $dist(v)$ 的值。

Bellman-Ford 算法如下:

@@ -114,7 +114,7 @@ Bellman-Ford 算法如下:
while (1) for each edge(u, v) relax(u, v);
```

当一次循环中没有 $relax$ 操作成功时停止。
当一次循环中没有松弛操作成功时停止。

每次循环是 $O(m)$ 的,那么最多会循环多少次呢?

@@ -124,11 +124,9 @@ while (1) for each edge(u, v) relax(u, v);

我们考虑最短路存在的时候。

由于一次 $relax$ 会使(被 $relax$ 的)最短路的边数至少 $+1$ ,而最短路的边数最多为 $n-1$ 。
由于一次松弛操作会使最短路的边数至少 $+1$ ,而最短路的边数最多为 $n-1$ 。

所以最多(连续) $relax$  $n-1$ 次……( $relax$ 一定是环环相扣的,不然之前就能被 $relax$ 掉)

所以最多循环 $n-1$ 次。
所以最多执行 $n-1$ 次松弛操作,即最多循环 $n-1$ 次。

总时间复杂度 $O(NM)$ 。 **(对于最短路存在的图)** 

@@ -152,7 +150,7 @@ for (i = 1; i < n; i++) {

给一张有向图,问是否存在负权环。

做法很简单,跑 Bellman-Ford 算法,如果有个点被 $relax$ 成功了 $n$ 次,那么就一定存在。
做法很简单,跑 Bellman-Ford 算法,如果有个点被松弛成功了 $n$ 次,那么就一定存在。

如果 $n-1$ 次之内算法结束了,就一定不存在。

@@ -160,11 +158,11 @@ for (i = 1; i < n; i++) {

即 Shortest Path Faster Algorithm。

很多时候我们并不需要那么多无用的 $relax$ 操作。
很多时候我们并不需要那么多无用的松弛操作。

很显然,只有上一次被 $relax$ 的结点,所连接的边,才有可能引起下一次的 $relax$ 
很显然,只有上一次被松弛的结点,所连接的边,才有可能引起下一次的松弛操作

那么我们用队列来维护“哪些结点可能会引起 $relax$ ”,就能只访问必要的边了。
那么我们用队列来维护“哪些结点可能会引起松弛操作”,就能只访问必要的边了。

```text
q = new queue();
@@ -182,7 +180,7 @@ while (!q.empty()) {
}
```

SPFA 时间复杂度为 $O(kM)~ (k\approx 2)$ (玄学),但 **理论上界** 为 $O(NM)$ ,精心设计的稠密图可以随便卡掉 SPFA,所以考试时谨慎使用(NOI 2018 卡 SPFA)。
SPFA 在随机图上的期望时间复杂度为 $O(kM)~ (k\approx 2)$ ,但最坏情况下的时间复杂度为 $O(NM)$ ,事实上使 SPFA 跑到时间复杂度上限的图非常容易构造,所以考试时谨慎使用(NOI 2018 卡 SPFA)。

#### SPFA 的优化之 SLF

@@ -212,9 +210,8 @@ IPA:/ˈdikstrɑ/或/ˈdɛikstrɑ/。

然后重复这些操作:

(1) $relax$ 那些刚刚被加入第一个集合的结点的所有出边。

(2)从第二个集合中,选取一个最短路长度最小的结点,移到第一个集合中。
1. 对那些刚刚被加入第一个集合的结点的所有出边执行松弛操作。
2. 从第二个集合中,选取一个最短路长度最小的结点,移到第一个集合中。

直到第二个集合为空,算法结束。

@@ -238,9 +235,9 @@ IPA:/ˈdikstrɑ/或/ˈdɛikstrɑ/。

再证明第一个集合中的元素的最短路已经确定。

第一步,一开始时成立(基础),在每一步中,加入集合的元素一定是最大值,且是另一边最小值, $relax$ 又是加上非负数,所以仍然成立。(归纳)(利用非负权值的性质)
第一步,一开始时成立(基础),在每一步中,加入集合的元素一定是最大值,且是另一边最小值, 每次松弛操作又是加上非负数,所以仍然成立。(归纳)(利用非负权值的性质)

第二步,考虑每次加进来的结点,到他的最短路,上一步必然是第一个集合中的元素(否则他不会是第二个集合中的最小值,而且有第一步的性质),又因为第一个集合已经全部 $relax$ 过了,所以最短路显然确定了。
第二步,考虑每次加进来的结点,到他的最短路,上一步必然是第一个集合中的元素(否则他不会是第二个集合中的最小值,而且有第一步的性质),又因为第一个集合内的点已经全部松弛过了,所以最短路显然确定了。

```text
H = new heap();