網絡最大流:Dinic

0.前置知識

存圖方式(鄰接表鄰接矩陣),圖的遍歷(dfsbfs

1.引入

我們舉個例子吧:
有一個水管工,叫超級嗎力熬,他會造水管,有一天他造了一個水管網絡,展現出來的形式就像一個圖。其中有一個點只有出邊,是用來輸入水的,還有一個點只有入邊,是用來輸出水的。點之間有一些管子,這些管子都有各自單位時間內的容量,現在超級嗎力熬想知道,他的管子在單位時間裏最多能流多少水。

2.概念

網絡流有一大堆神祕而又陰森的概念。

  • 源點:顧名思義,就是輸入水的那個點,一般用s表示
  • 匯點:顧名思義,就是輸出水的那個點,一般用t表示。。。
  • 容量:顧名思義。。。一條邊單位時間內的的容量
  • 殘餘網絡:進行增廣後剩餘的網絡
  • 増廣:

増廣就是在殘餘網絡中尋找從源點到匯點的可行路徑(増廣路),並將該路徑上的所有邊的容量減去路徑中的最小容量,形成新的殘餘網絡
例如:
在這裏插入圖片描述
如果當前有這樣一個殘餘網絡,那麼 s 4 1 t s\rightarrow4\rightarrow1\rightarrow t 就是一條増廣路,最小容量是4,進行増廣過後就形成了這樣一張圖:
在這裏插入圖片描述
如何尋找増廣路?直接dfs即可。

  • 反向邊:

有時候,程序増廣的時候會出現爆炸性錯誤,例如還是那個圖:
在這裏插入圖片描述
有兩條増廣路,萬一程序選錯了怎麼辦?
這時就要請出反向邊了。
每次増廣的時候,在殘餘網絡上逆着増廣路徑建容量與増廣路徑最小容量相等的反向邊,比如剛纔那張圖,就順着 t 1 4 s t\rightarrow1\rightarrow4\rightarrow s 建容量爲4的邊。
這就給了程序一個反悔的機會。

3.Dinic的優化

前面的概念講的好多啊,都把網絡流的樸素算法講完了。。。
Dinic的優化就是他用bfs建立了由s開始的一個分層圖,每次尋找増廣路時必須讓邊上的層數嚴格遞增,這樣就不會陷入毒瘤數據卡成的死循環,比如這樣的著名毒瘤數據:
在這裏插入圖片描述
在這個數據中,如果用樸素算法,就會讓中間容量爲1的邊上下抖動抽搐,等到他抽了999次的時候才把上面和下面的999減沒。如果用Dinic,兩次直接求出999+999。

4.代碼

404 Not Found(Click for more information) 完結!