龟速补上欠下的账 ing……
写完发现读着好晦涩,但数学不就是这样的吗🌚
基本概念/符号表示
为了方便下文叙述,现做如下规定/定义:
G = ( V , E ) G = (V, E) G = ( V , E ) 是有向、无平行边的图,每条边边权为正,其中有一个源点 (source)s s s 和汇点 (sink)t t t 满足:没有一条边以 t t t 为起点,或以 s s s 为终点。
对某边 e ∈ E e \in E e ∈ E ,记该边边权为 c ( e ) c(e) c ( e ) 。
若某点集 A ⊆ V A \subseteq V A ⊆ V ,规定 E A − = ( A × ( V ∖ A ) ) ∩ E , E A + = ( ( V ∖ A ) × A ) ∩ E E_A^- = (A \times (V \setminus A)) \cap E, E_A^+ = ((V \setminus A) \times A) \cap E E A − = ( A × ( V ∖ A )) ∩ E , E A + = (( V ∖ A ) × A ) ∩ E ,即 E A − , E A + E_A^-, E_A^+ E A − , E A + 分别表示“离开 A A A ”和“到达 A A A ”的边集。相似地,对于某一节点 v ∈ V v \in V v ∈ V ,记 E v − = ( { v } × ( V ∖ { v } ) ) ∩ E , E v + = ( ( V ∖ { v } ) × { v } ) ∩ E E_v^- = (\{v\} \times (V \setminus \{v\})) \cap E, E_v^+ = ((V \setminus \{v\}) \times \{v\}) \cap E E v − = ({ v } × ( V ∖ { v })) ∩ E , E v + = (( V ∖ { v }) × { v }) ∩ E 。
A ⊔ B A \sqcup B A ⊔ B 表示两个集合 A , B A, B A , B 的不交并 。
若两个点集 A , B ⊆ V A, B \subseteq V A , B ⊆ V 满足 V = A ⊔ B V = A \sqcup B V = A ⊔ B ,且有:u ∈ A , v ∈ B u \in A, v \in B u ∈ A , v ∈ B 以及子图 G A = ( A , ( A × A ) ∩ E ) , G B = ( B , ( B × B ) ∩ E ) G_A=(A, (A \times A) \cap E), G_B = (B, (B \times B) \cap E) G A = ( A , ( A × A ) ∩ E ) , G B = ( B , ( B × B ) ∩ E ) 分别连通,则称 ( A , B ) (A, B) ( A , B ) 为 G G G 的割(cut) (或 s s s -t t t 割)。
(用通俗语言描述就是将 G G G 一刀“砍”成两半,其中 s s s 和 t t t 不在同一边)
一个割的容量 (capacity)定义为:c a p ( A , B ) = ∑ e ∈ E A − c ( e ) \mathop{\mathrm{cap}}(A, B) = \sum_{e \in E_A^-}c(e) cap ( A , B ) = ∑ e ∈ E A − c ( e ) 。
最小割问题 (Minimum Cut Problem):求网络流图 G G G 容量最小的 s s s -t t t 割。
若一个函数 f : E → R f: E \rightarrow \mathbb{R} f : E → R 满足:
∀ e ∈ E , 0 ≤ f ( e ) ≤ c ( e ) \forall e \in E,\ 0 \leq f(e) \leq c(e) ∀ e ∈ E , 0 ≤ f ( e ) ≤ c ( e ) ,其中 c ( e ) c(e) c ( e ) 又称该边的容量 (capacity);
∀ v ∈ V ∖ { s , t } , ∑ e ∈ E v + f ( e ) = ∑ e ∈ E v − f ( e ) \forall v \in V \setminus \{s, t\},\ \sum_{e \in E_v^+} f(e) = \sum_{e \in E_v^-} f(e) ∀ v ∈ V ∖ { s , t } , ∑ e ∈ E v + f ( e ) = ∑ e ∈ E v − f ( e ) (流量守恒,Flow Conservation )
称 f f f 为网络流图 G G G 的一个流 (flow)。其流量 (flow value)定义为 v ( f ) = ∑ e ∈ E s − f ( e ) v(f) = \sum_{e \in E_s^-} f(e) v ( f ) = ∑ e ∈ E s − f ( e ) 。
最大流问题 (Maximum Flow Problem):求网络流图 G G G 流量最大的流。
「流」和「割」
下面尝试说明:最大流问题和最小割问题是等价的。
首先引出流量引理 (Flow Value Lemma):对于任一流 f f f 和任一 s s s -t t t 割 ( A , B ) (A, B) ( A , B ) ,从 A A A 流向 B B B 的总流量等于离开 s s s 的总流量,即:
∑ e ∈ E A − f ( e ) − ∑ e ∈ E A + f ( e ) = v ( f ) \sum_{e \in E_A^-} f(e) - \sum_{e \in E_A^+} f(e) = v(f) e ∈ E A − ∑ f ( e ) − e ∈ E A + ∑ f ( e ) = v ( f )
证明 :由流量守恒:
v ( f ) = ∑ e ∈ E s − f ( e ) = ∑ v ∈ A ( ∑ e ∈ E v − f ( e ) − ∑ e ∈ E v + f ( e ) ) = ∑ e ∈ E A − f ( e ) − ∑ e ∈ E A + f ( e ) \begin{align*}
v(f) &= \sum_{e \in E_s^-} f(e) \\
&= \sum_{v \in A} \left( \sum_{e \in E_v^-} f(e) - \sum_{e \in E_v^+} f(e) \right) \\
&= \sum_{e \in E_A^-} f(e) - \sum_{e \in E_A^+} f(e)
\end{align*} v ( f ) = e ∈ E s − ∑ f ( e ) = v ∈ A ∑ e ∈ E v − ∑ f ( e ) − e ∈ E v + ∑ f ( e ) = e ∈ E A − ∑ f ( e ) − e ∈ E A + ∑ f ( e )
由该引理,可以得出流和割的弱对偶性 (Weak Duality):对于任一流 f f f 和任一 s s s -t t t 割 ( A , B ) (A, B) ( A , B ) ,f f f 的流量 v ( f ) v(f) v ( f ) 至多等于 ( A , B ) (A, B) ( A , B ) 的容量 c a p ( A , B ) \mathop{\mathrm{cap}}(A, B) cap ( A , B ) 。
证明 :
v ( f ) = ∑ e ∈ E A − f ( e ) − ∑ e ∈ E A + f ( e ) ≤ ∑ e ∈ E A − f ( e ) ≤ ∑ e ∈ E A − c ( e ) = c a p ( A , B ) \begin{align*}
v(f) &= \sum_{e \in E_A^-} f(e) - \sum_{e \in E_A^+} f(e) \\
&\leq \sum_{e \in E_A^-} f(e) \\
&\leq \sum_{e \in E_A^-} c(e) \\
&= \mathop{\mathrm{cap}}(A, B)
\end{align*} v ( f ) = e ∈ E A − ∑ f ( e ) − e ∈ E A + ∑ f ( e ) ≤ e ∈ E A − ∑ f ( e ) ≤ e ∈ E A − ∑ c ( e ) = cap ( A , B )
引理 :若存在流 f f f 和割 ( A , B ) (A, B) ( A , B ) 使得 v ( f ) = c a p ( A , B ) v(f) = \mathop{\mathrm{cap}}(A, B) v ( f ) = cap ( A , B ) ,则 f f f 是一个最大流,而 ( A , B ) (A, B) ( A , B ) 是一个最小割。
对于一张网络流图 G G G ,若已存在一个流 f f f ,我们希望获知是否能对这个流进行修改,比如更改某一条边的流量或发送一条从 s s s 到 t t t 的新流。因此我们需要一张新图 G f = ( V , E f ) G_f = (V, E_f) G f = ( V , E f ) 来刻画这个流之外“剩下”的状态,其中 G f G_f G f 和 E f E_f E f 分别称作剩余图 (residual graph)和剩余边集 (set of residual edges)。
若 e = ( u , v ) ∈ E e = (u, v) \in E e = ( u , v ) ∈ E ,则它对应的剩余边 (residual edge)为 e e e 本身以及其反向边 e R = ( v , u ) e^R = (v, u) e R = ( v , u ) 。这两条边的容量(用 c f c_f c f 表示)分别为:
c f ( e ) = c ( e ) − f ( e ) c f ( e R ) = f ( e ) \begin{align*}
c_f(e) &= c(e) - f(e) \\
c_f(e^R) &= f(e)
\end{align*} c f ( e ) c f ( e R ) = c ( e ) − f ( e ) = f ( e )
为保证剩余图依然是一张网络流图,规定 e e e 或 e R e^R e R 在 E f E_f E f 中当且仅当其容量非零。即:
E f = { e ∈ E ∣ f ( e ) < c ( e ) } ∪ { e R ∣ e ∈ E , f ( e ) > 0 } E_f = \{e \in E \mid f(e) < c(e)\} \cup \{e^R \mid e \in E, f(e) > 0 \} E f = { e ∈ E ∣ f ( e ) < c ( e )} ∪ { e R ∣ e ∈ E , f ( e ) > 0 }
若 s , t s, t s , t 在 G f G_f G f 中依然连通,连接这两个节点的简单路径称为增广路径 (augmenting path)或增广路 。增广路上最小的剩余边容量称为瓶颈容量 (bottleneck capacity),记作 c b ( G f , p ) c_b(G_f, p) c b ( G f , p ) 。若 f f f 是 G G G 上的一个流,而 p p p 是 G f G_f G f 上一条增广路,那么将 p p p 加入(augment to)f f f 中得到 f ’ f’ f ’ ,有 v ( f ’ ) = v ( f ) + c b ( G f , p ) v(f’) = v(f)+c_b(G_f, p) v ( f ’ ) = v ( f ) + c b ( G f , p ) 。
这条性质称作增广路的主要特性 (Key Property)。一般地,若 f f f 是 G G G 上的一个流,而 g g g 是 G f G_f G f 上的一个流,那么 f + g f+g f + g 是 G G G 上的一个流,其中 v ( f + g ) = v ( f ) + v ( g ) v(f+g) = v(f) + v(g) v ( f + g ) = v ( f ) + v ( g ) ,对任意 e ∈ E e \in E e ∈ E ,有 ( f + g ) ( e ) = f ( e ) + g ( e ) − g ( e R ) (f+g)(e) = f(e) + g(e) - g(e^R) ( f + g ) ( e ) = f ( e ) + g ( e ) − g ( e R ) 。
最大流最小割定理
由增广路径的主要特性,我们可以获得一个基本的求最大流的思路:
若剩余图中仍存在增广路径,则沿这条路径发送一个流(即加入到已求的流中),重复执行这个步骤直到增广路径不存在。
这个思路称作 Ford-Fulkerson 方法 。该方法的正确性由增广路定理 (Augmenting Path Theorem)得到:流 f f f 是最大流当且仅当剩余图中不存在增广路。
此外,由上述提到的弱对偶性,我们自然地想到:一张图的最大流等于最小割。这就是最大流最小割定理 (Max-flow Min-cut Theorem)的内容。下面对这两个定理进行证明。
要证明上述定理,只需说明以下三个命题互相等价:
a ) a) a ) 存在一个割 ( A , B ) (A, B) ( A , B ) 使得 v ( f ) = c a p ( A , B ) v(f) = \mathop{\mathrm{cap}}(A, B) v ( f ) = cap ( A , B )
b ) b) b ) 流 f f f 是最大流
c ) c) c ) f f f 对应的剩余图 G f G_f G f 中不存在增广路
证明 :
a ) ⇒ b ) a) \Rightarrow b) a ) ⇒ b ) 由「弱对偶性」的推论得出(任一流的流量小于等于任一割的容量,则等于割容量的流为最大流)。
b ) ⇒ c ) b) \Rightarrow c) b ) ⇒ c ) 只需证明其逆否命题。若 G f G_f G f 中存在增广路 p p p ,由增广路的主要特性,可构造 f ′ f' f ′ 使得 v ( f ’ ) = v ( f ) + c b ( G f , p ) > v ( f ) v(f’) = v(f) + c_b(G_f, p) > v(f) v ( f ’ ) = v ( f ) + c b ( G f , p ) > v ( f ) ,因此 f f f 不是最大流。
c ) ⇒ a ) c) \Rightarrow a) c ) ⇒ a ) 假设 f f f 对应的剩余图 G f G_f G f 中不存在增广路,令 A A A 为 s s s 在 G f G_f G f 中能到达的点的集合,B = V ∖ A B = V \setminus A B = V ∖ A ,显然有 s ∈ A , t ∈ B s \in A, t \in B s ∈ A , t ∈ B 。由假设知,G f G_f G f 不存在“离开 A A A ”的边,因此有 ∀ e ∈ E A − , f ( e ) = c ( e ) \forall e \in E_A^-, f(e) = c(e) ∀ e ∈ E A − , f ( e ) = c ( e ) 以及 ∀ e ∈ E A + , f ( e ) = 0 \forall e \in E_A^+, f(e) = 0 ∀ e ∈ E A + , f ( e ) = 0 (否则会产生“离开 A A A ”的剩余边,和假设矛盾)。于是由流量引理有:
v ( f ) = ∑ e ∈ E A − f ( e ) − ∑ e ∈ E A + f ( e ) = ∑ e ∈ E A − c ( e ) = c a p ( A , B ) \begin{align*}
v(f) &= \sum_{e \in E_A^-} f(e) - \sum_{e \in E_A^+} f(e) \\
&= \sum_{e \in E_A^-} c(e) \\
&= \mathop{\mathrm{cap}}(A, B)
\end{align*} v ( f ) = e ∈ E A − ∑ f ( e ) − e ∈ E A + ∑ f ( e ) = e ∈ E A − ∑ c ( e ) = cap ( A , B )
至此,增广路定理和最大流最小割定理都能得到证明。
Ford-Fulkerson 的实现
下面假定所有边容量均为 [ 1 , ∑ e ∈ E s − c ( e ) ] \left[1, \sum_{e \in E_s^-} c(e)\right] [ 1 , ∑ e ∈ E s − c ( e ) ] 内的正整数,且满足每条边的流量和剩余边容量均为正整数(整性不变性)。
(如果允许边的容量为无理数,无法证明 Ford-Fulkerson 算法能在有限时间内停止,或得到实际的最大流。维基百科 上给出了该情形下的一个反例。)
由于每次流量至少增加 1 1 1 ,不难证明 Ford-Fulkerson 方法能在至多 v ( f ∗ ) ≤ C v(f^*) \leq C v ( f ∗ ) ≤ C 次迭代内结束,其中 f ∗ f^* f ∗ 为最大流,C C C 为某一正整数(有穷性 )。
推论 :若 C = 1 C = 1 C = 1 ,则 Ford-Fulkerson 运行时间为 O ( m n ) \mathrm{O}(mn) O ( mn ) ,其中 m = ∣ E ∣ , n = ∣ V ∣ m = |E|, n = |V| m = ∣ E ∣ , n = ∣ V ∣ 。BFS 遍历时间为 O ( m + n ) \mathrm{O}(m+n) O ( m + n ) ,添加增广路耗时 O ( n ) \mathrm{O}(n) O ( n ) 。
由整性不变性和增广路定理,不难证明:若网络流图中每条边权均为正整数,则存在一个最大流满足每条边的流量均为正整数。
现在讨论如何找到增广路并快速求出最大流。
“容量缩放”(Capacity-Scaling)法
要想提高寻找增广路并且求得最大流的效率,一个直观的思路就是找到尽可能“短且胖 ”(即遍数少、瓶颈容量大)的增广路径。
首先,对于某一容量 Δ \Delta Δ ,令 G f ( Δ ) G_f(\Delta) G f ( Δ ) 表示剩余图中边容量不小于 Δ \Delta Δ 的部分,即 G f ( Δ ) = ( V , E f ( Δ ) ) G_f(\Delta) = (V, E_f(\Delta)) G f ( Δ ) = ( V , E f ( Δ )) ,其中 E f ( Δ ) = { e ∈ E f ∣ c f ( e ) ≥ Δ } E_f(\Delta) = \{e \in E_f \mid c_f(e) \geq \Delta\} E f ( Δ ) = { e ∈ E f ∣ c f ( e ) ≥ Δ } 。观察到:G f ( Δ ) G_f(\Delta) G f ( Δ ) 中任一增广路的容量一定大于等于 Δ \Delta Δ ,因而我们可以维护这个 Δ \Delta Δ (称为缩放因子,scaling parameter ),当 G f ( Δ ) G_f(\Delta) G f ( Δ ) 中不存在增广路时缩小 Δ \Delta Δ 值,直到 Δ \Delta Δ 为 1 1 1 为止,此时得到的流就是我们要求的最大流(G f ( 1 ) G_f(1) G f ( 1 ) 不存在增广路等价于 G f G_f G f 不存在增广路,则由增广路定理 显然可得)。
现实中,为提高运行效率,一般令 Δ \Delta Δ 初值为不超过 max e ∈ E s − { c ( e ) } \max_{e \in E_s^-}\{c(e)\} max e ∈ E s − { c ( e )} 的 最大的 2 2 2 的幂,每次缩放时将 Δ \Delta Δ 减半,则 Δ \Delta Δ 始终为 2 2 2 的某一次方,显然也满足上文提到的整性不变性 。
下面提出三个引理:
引理 1 :该方法中有 1 + ⌊ log 2 C ⌋ 1+\left\lfloor \log_2 C \right\rfloor 1 + ⌊ log 2 C ⌋ 次迭代,其中 C C C 为上文有穷性 处提到的迭代上界。
证明 :由题目假设,显然有 Δ ≤ max e ∈ E s − { c ( e ) } ≤ v ( f ∗ ) ≤ C \Delta \leq \max_{e \in E_s^-}\{c(e)\} \leq v(f^*) \leq C Δ ≤ max e ∈ E s − { c ( e )} ≤ v ( f ∗ ) ≤ C ,则缩放阶段数为 1 + ⌊ log 2 Δ ⌋ ≤ 1 + ⌊ log 2 C ⌋ 1+\left\lfloor \log_2 \Delta \right\rfloor \leq 1+\left\lfloor \log_2 C \right\rfloor 1 + ⌊ log 2 Δ ⌋ ≤ 1 + ⌊ log 2 C ⌋ 。
引理 2 :令 f f f 为一次迭代结束时的流(即,此时 G f ( Δ ) G_f(\Delta) G f ( Δ ) 不存在增广路),则 v ( f ∗ ) ≤ v ( f ) + m Δ v(f^*) \leq v(f) + m\Delta v ( f ∗ ) ≤ v ( f ) + m Δ 。
证明 :我们只需证明:此时存在一个割 ( A , B ) (A, B) ( A , B ) 使得 c a p ( A , B ) ≤ v ( f ) + m Δ \mathop{\mathrm{cap}}(A, B) \leq v(f) + m\Delta cap ( A , B ) ≤ v ( f ) + m Δ 。令 A A A 为 s s s 在 G f ( Δ ) G_f(\Delta) G f ( Δ ) 中能到达的点的集合,B = V ∖ A B = V \setminus A B = V ∖ A ,则和之前证明类似地,有:
v ( f ) = ∑ e ∈ E A − f ( e ) − ∑ e ∈ E A + f ( e ) ≥ ∑ e ∈ E A − ( c ( e ) − Δ ) − ∑ e ∈ E A + Δ ≥ ∑ e ∈ E A − c ( e ) − m Δ = c a p ( A , B ) − m Δ \begin{align*}
v(f) &= \sum_{e \in E_A^-} f(e) - \sum_{e \in E_A^+} f(e) \\
&\geq \sum_{e \in E_A^-} \left( c(e) - \Delta \right) - \sum_{e \in E_A^+} \Delta \\
&\geq \sum_{e \in E_A^-} c(e) - m\Delta \\
&= \mathop{\mathrm{cap}}(A, B) - m\Delta
\end{align*} v ( f ) = e ∈ E A − ∑ f ( e ) − e ∈ E A + ∑ f ( e ) ≥ e ∈ E A − ∑ ( c ( e ) − Δ ) − e ∈ E A + ∑ Δ ≥ e ∈ E A − ∑ c ( e ) − m Δ = cap ( A , B ) − m Δ
对第一个不等号的推导稍作解释:由假设知,G f G_f G f 中不存在容量大于等于 Δ \Delta Δ 的增广路;更精确地说,G f G_f G f 中离开 A A A 的剩余边权值均小于 Δ \Delta Δ 。因此有 ∀ e ∈ E A − , f ( e ) ≥ c ( e ) − Δ \forall e \in E_A^-,\ f(e) \geq c(e) - \Delta ∀ e ∈ E A − , f ( e ) ≥ c ( e ) − Δ 以及 ∀ e ∈ E A + , f ( e ) ≤ Δ \forall e \in E_A^+,\ f(e) \leq \Delta ∀ e ∈ E A + , f ( e ) ≤ Δ 。
引理 3 :每一次迭代最多加入 2 m 2m 2 m 条增广路。
证明 :令 f f f 为某一次迭代开始时的流,由引理 2 有:v ( f ∗ ) ≤ v ( f ) + m ⋅ 2 Δ v(f^*) \leq v(f) + m \cdot 2\Delta v ( f ∗ ) ≤ v ( f ) + m ⋅ 2Δ ,又由算法知,每次增加的流量大小为 Δ \Delta Δ ,显然可得。
由上述三条引理知,该算法的时间复杂度为 O ( m 2 log C ) \mathrm{O}(m^2\log C) O ( m 2 log C ) ,其中一共加入 O ( m log C ) \mathrm{O}(m\log C) O ( m log C ) 条增广路,搜索每条增广路(BFS)需要 O ( m ) \mathrm{O}(m) O ( m ) 的时间。
Edmonds–Karp/Dinic 算法
Edmonds–Karp/Dinic 算法思路和 Ford-Fulkerson 一样,不过时间复杂度可以优化至 O ( n 2 m ) \mathrm{O}(n^2m) O ( n 2 m ) 。该算法的思想是:每次用 BFS 寻找一条增广路,并沿该路径发送一条大小为其瓶颈容量的流;重复该过程直到 s s s 和 t t t 不连通 。算法有穷性和正确性略去不证,下面对时间复杂度进行简单说明。
由 BFS 的性质,每次找到的增广路均为当前剩余图中最短的,且一次迭代的时间复杂度为 O ( m n ) \mathrm{O}(mn) O ( mn ) (由 Ford-Fulkerson 有穷性推论)。又因为每次发送的流大小为增广路的瓶颈容量,则至少有一条剩余边被“填满”。因此下一条搜索到该边时路径长度一定大于此次迭代的路径,且不超过 n n n 。由上述可知每次找到的最短增广路长度是单调递增的,迭代次数为 O ( n ) \mathrm{O}(n) O ( n ) 。因此总时间复杂度为 O ( n 2 m ) \mathrm{O}(n^2m) O ( n 2 m ) 。
该算法还可以进一步优化(称为 ISAP )。此外还存在一个忽略流守恒性、从比较“物理”的角度来求解的预留推进算法 。请参阅 OI Wiki 。