網路流 (一) 最大流的原理圖解
嗯…於是學一波網路流罷
之前學過一波,不過失敗了orz
希望這次能學成功(x)
建模
想象一下,你在排程貨車運輸(不是最小生成樹+LCA那道題放心吧),但是有些橋是有載重限制的。比如下圖:
綠色的邊表示橋,上面的數字表示載重。
老闆打算從A到G。
顯然,作為一個老闆,超載是不合適的,姑且不論貨物安全,還有可能受到法律懲罰!那麼,最多能一次載多少貨物呢?
在解決這個問題之前,我們先為這一模型定義一些概念。
出發點成為源點,也就是
終點稱為匯點,也就是
而每條邊上的最大載重稱為容量,例如
顯然,由於不可能超過限重,
並且,貨物顯然不能損失吧,所以源點和匯點的流量是相同的,對於所有點,流入的流量和流出是相同的。
建模完成,接下來就是求解了。
增廣
首先,我們定義一種合理的載重方法為可行流。比如下圖:
黃色的代表一個可行流,其中數字第一個表示容量,第二個為流量。
我們知道,零流就是一個典型代表——畢竟,它並不會超過容量。
然後,我們就可以開始增廣操作了。其實增廣是一種自然而然的想法:假定路徑
這樣說不是很明白,舉個栗子(為了方便我畫圖起見我們姑且換一個圖)來演示一下過程好了。
好的,現在先yy一下圖中存在0流。這裡我們寫了一個東西叫做剩餘,表示的是當前這中方式下還有多少流能夠匯入。
那麼,增廣開始。不妨採用BFS的思想,第一次找到了路徑
我們發現,這條路線上最多能增廣2單位的流,所以我們將流注入。
圖中的
此時變成了這種樣子。然後我們仍然BFS,發現了
沒毛病!然後再去增廣
掃視一遍,發現未有能增廣者,結束增廣。
完成了,可喜可賀。由於源點和匯點的流量相同,我們知道,最大流就是6個單位。為之四顧,為之躊躇滿志。
但是,在你躍躍欲試去寫網路流模板之前,不得不先潑一瓢涼水——
如果此時BFS沒有去增廣
(上面的
繼續:
驚悚的事情發生了。
沒錯,之後沒有辦法增廣了,但是!此時我們求出的最大流是4!
這是否證明我們的貪心思路是錯的呢?
機制的珂學家們引入了下面的概念,完美的迴避掉了這個致命的漏洞——
反向弧
既然這麼貪不一定是對的,那麼我們就可以引入一種後悔機制,來提供反悔的機會。
怎麼搞呢?我們可以每增廣一次,就建立一條反向邊。
仍然是上面的例子,在對
注意,這裡的
然後呢——我們發現,
這個圖可能稍微有些亂,紅色的是我們增廣的東西,綠色是增廣建的反向邊。
當然,繼續掃一遍,發現
沒有可以增廣的了——完成DAZE!
所以最終的結果就是6。
那麼可能有人會問了——上面我們走了
上面就是一切網路流問題的基礎,也是最大流的原理。下一篇文章,我們考慮其實現辦法。