想像一下…
這些東西都有這些特性
而我們定義這個 s-t 流的流量為 \( \abs{f} = \sum_{v \in V} f(s, v) \)
流量最大的一個流,也就是最大流!
一點一點慢慢增加流量
問:可以增加多少流量?
直到有一天流不了。
Question: 這樣是否就是一個最大流?
Answer: No!
還記得
流量對稱 :
\( f(u, v) = -f(v, u), \; \forall (u, v)\)
\( -3 < 0 \) ,可以流過去!
Question: 考慮負向邊之後,是否就是一個最大流?
Answer: Yes!
在剩餘網路上不斷找路增加流量!
假設找到了一條路徑 \( P = s \to v_1 \to v_2 \to \cdots \to v_n \to t \)。
我們先進行一段 C++ Coding 宣導。
int f = 0
while (tf = find_path()) {
f += tf;
}
return f;
int find_path(int u = S, int curf = INF) {
if (u == T) return curf; // Done!
for (auto &e: E[u]) {
int v = e.dest, f = e.f, tf;
if (tf = find_path(v, min(curf, f))) {
auto rev = e.rev;
e.f -= tf;
ref.f += tf;
return tf;
}
}
return 0;
}
沒有保證!
在流量是整數的時候,每次流量至少增加 \( 1 \),
複雜度 \( \ord{E \abs{f}} \)。
int f = 0
while (tf = find_shortest_path()) {
f += tf;
}
return f;
有差嗎?
只差在 Edmonds-Karp 每次規定找最短的一條擴充路徑。
差多少呢?
差非常多! 複雜度變成 \( \ord{V E^2} \)
不但跟流量大小無關,無理數也會 work !
Edmonds-Karp 的一個小優化。
每次擴充後其實只有一些點的 \( d(v) \) 會變。
一次把所有長度是 \( k \) 的擴充路徑都擴充完。
每次 \( \ord{k E} \),總共 \( \ord{V^2 E} \)。
裸的最大流,BJ4
我們先說一下定義
二分圖匹配有不少應用
觀察一個路徑 \( v_1 \to v_2 \to \cdots \to v_n \)
每一個中間走到的點 \( +2 \) ,兩端 \( +1 \)。
一個有向圖有歐拉迴路的條件是所有點都滿足 \( \deg^+(v) = \deg^-(v) \),
混合圖呢?
其實就是要把每一個無向邊都定向成有向圖
最後要求每一個點的 \( \deg^+(v) = \deg^-(v) \)。
令還沒有算無向邊時 \( \delta(v) = \deg^-(v) - \deg^+(v) \)。
如果我們把一個邊定成 \( u \to v \) 後, \( \delta(u) \gets \delta(u) - 1, \delta(v) \gets \delta(v) + 1 \)。
可以想作一單位的 $\delta$ 從 \( u \) 流到了 \( v \)。
對於那些 \( \delta(v) > 0 \) 的,也就是需要流出 \( \delta(v) \) 的,我們就建 \( s \to v \)。
對於那些 \( \delta(v) < 0 \) 的,同理建 \( v \to t \)。
可以補好補滿 \( \iff \abs{f} = \sum_{\delta(v) > 0} \delta(v) \)
問題常常是一體兩面
某個求最大值的問題常常等價於另一個求最小值的問題
那最大流的對偶是什麼呢?
想像一下…
一個網路的最大流,就是那些被
「堵住」的水管的淨流量。
這些堵住的水管會把點分成兩群。
而最大流的對偶問題正是最小割。
(1) \( \implies \) (2) 前面講過。
找所有在剩餘網路上, \( s \) 連的到的點,令其為 \( S \), 其他點就是 \( T \)。
\( t \) 不在 \(S\) 中。
這個 cut 上的邊都要流滿,否則有路徑。
\( C \leq \abs{f} \)
由截流知 \( \abs{f} \leq C \)
\( \abs{f} = C \)
(3) \( \implies \) (1) 也證完了。
這個引理也告訴了我們,找所有在剩餘網路上, \( s \) 連的到的點,令其為 \( S \), 其他點就為 \( T \),就恰好是一個 s-t cut。
裸的最小割,BJ4
先看個例題
分成要買/不要買的機器,要生產/不要生產的產品。
把要的就分到 \( S \),不要的就分到 \( T \)。
當然,還是要建模使得求出的答案即是題目要的。
回到那一題
和最大流時一樣,我們要求一個流量最大的流。
但現在每個邊除了有流量上限以外,還有一個價格 \( k(u, v) \), 表示每單位流過要付多少錢。
最後總花費是 \[ k(f) = \sum_{f(u, v) > 0} k(u, v) \cdot f(u, v) \]
如何修改前面的使得可以找一個最小花費的最大流?
我們先想剩餘網路要怎麼做修改。
流量應該不變。
那剩餘網路的花費 \( k_{f} (u, v) \) 如何設?
如果在原圖有一條有向邊 \( u \to v \) , Cost 為 \( k(u, v) \)。
由這兩個引理我們可以知道只要每次都找最短路擴充,直到最大流即可。
只是現在「最短路」並非邊數最少的路徑,而是花費總合最少的路徑!
int f = 0
while (tf = find_mincost_path()) {
f += tf;
}
return f;
可以用任何能處理負邊的演算法,如 SPFA。
總複雜度是 \( \ord{SP \cdot \abs{f}} \)。
很多最大流的題目都可以推擴成花費流。
二分搜答案,假設最大密度為 \( k \)。
\[ \abs{E'} - k \abs{V'} \geq 0 \iff \max_{H = (V', E')} \abs{E'} - k \abs{V'} \geq 0 \]
\[ \abs{E'} = \frac{1}{2} \sum_{v \in V'} \deg_H(v) \]
\[ \deg_H(v) = \deg_G(v) - \sum_{\substack{u \notin H \\ (v, u) \in E}} 1 \]
\[ \Leftrightarrow \; - \min_{H = (V', E')} \sum_{v \in V'} \left( \left(2k - \deg_G(v) \right) + \sum_{\substack{u \notin H \\ (v, u) \in E}} 1 \right) \geq 0 \]
分兩類問題!
如果有一個路徑 \( v_1 \to v_2 \to v_3 \cdots \)
就是 \( \texttt{next}(v_1) = v_2, \texttt{next}(v_2) = v_3 \)匹配!
不如先補滿下界。
但有些點的流量就不守恆了,進來的跟出來的差了 \( \delta(v) \)。
有沒有想到混合圖的歐拉回路那一題!
\( M(G) = C_v(G) \)
把點覆蓋轉成 min-cut !
很不一樣的是這次在 s 表示 (v in X and 不選 v) or (v in Y and 選 v)