把問題建模成網路流(modeling problems as network flow)
流理論真正的威力,往往不在流本身——而在於一個表面上毫無管路的問題,能被重塑成一個網路,使它的最大流或最小割正是你一直想要的答案。學會看出「選一個最佳子集」或「便宜地分開兩群」其實偷偷是個流問題,是演算法設計中槓桿最大的技能之一。
這門手藝是一小盒零件。二分圖匹配:源點到左(容量 1)、允許的配對由左到右、右到匯點(容量 1);最大流就是最大匹配。頂點容量:把頂點 v 拆成 v-入 與 v-出,以一條容量為 v 上限的邊相連,使一個節點只能承載那麼多。下界或「必用」邊:用輔助的源/匯邊來移轉流量。兩大族尤其常見。專案選取/最大權閉包:唯有先取某專案的前置條件才能取它;把利潤建模為源邊、成本為匯邊、前置條件為無限容量邊,最小割把「取」與「不取」分開以最大化淨利。影像分割:像素是頂點、相鄰對是邊(其容量是把它們分開的懲罰)、源與匯是兩個標籤,而最小割就是最便宜的前景/背景邊界。邊不相交路徑:給每條邊容量 1,最大流就等於最多的邊不相交 s-t 路徑數(Menger 定理)。
做得好,把問題建模成流能把看似需要暴力或巧妙臨時推理的問題,化為對某個最大流或最小割常式的一次多項式呼叫,且常附帶一張解釋最佳值的對偶憑證。讓它保持誠實的紀律是:建好網路後,你必須雙向證明對應關係——你問題的每個合法解都對映到一個同值的流/割,而每個整數流/割都能映回一個合法解——否則這個構造可能悄悄回答了另一個問題。也要知道邊界:許多問題確實不能歸約成流(一般匹配需要花朵;含相互衝突的二擇一約束的問題可能是 NP 困難),所以流是一個值得優先嘗試的強大預設,而非萬用鐵錘。
專案選取:兩個專案利潤 +10、+4,共用一項成本 -6 的工具且都需要它。源點 -> 各利潤(容量 = 利潤)、工具 -> 匯點(容量 = 成本)、各專案 -> 工具(容量 = 無限,強制「需要該工具」)。最小割等於總利潤減去最佳淨選取;此處兩個專案都做並付工具錢,淨得 10 + 4 - 6 = 8,正由割還原。
最小割把項目分成取/不取以最大化淨值——這個零件用無限容量的邊把約束編碼進去。
一個流模型好不好,全看它對應關係的證明。務必驗證每個問題解都對應一個同值的流/割、反之亦然;並記住並非一切都能歸約成流——一般匹配,以及許多二擇一約束問題,都不行。