网络流小结
網絡流小結
聯賽過后,雖然遺憾的沒拿到一等,但這不是止步不前的時候,于是我就學了學網絡流,學了這幾天,也該總結總結了......
網絡流其實就是一種圖論模型,在這種圖中,邊權變成了坑爹的流量,常見的最短路問題也變成了最大流-最小割問題
網絡圖和普通圖的最大區別也就是邊權不再是一個干干巴巴的數字,或者強賦意義的數量,而是真真正正地變成了一個具有實際意義的量—容量.我個人認為,這在現實中有著更廣泛的應用,網絡流量的分配,水流量的分配等諸多問題,都可以轉化為這個模型,網絡流具有十分廣泛的應用,或許這也是它被稱為圖論的最高奧義的原因之一吧.
網絡圖的存儲與普通的圖并無太大不同,這也得益于鄰接表這一巧妙的設計,我常用的存儲方式是這樣的:
struct edge {int to , next , flow ; // 意義與普通鄰接表相同,flow就是"邊權",也就是容量 } ;就是這么一個結構體,當然這其中沒有牽扯到費用,因為我還沒學習最小費用最大流這類問題
而只知道如何存儲是遠遠不夠的,這只是一個小基礎.網絡流的第一步就是最大流問題,問題描述為:
對于一張只具有一個源點和一個匯點的網絡,求出從源點到達匯點所能實現的最大流量.
這個問題與經典圖論問題的區別顯而易見,這時的邊權/容量是一種限制,并且是可變的.而且,顯然,對于一條路徑的最大流,限制它的是它的最小弧容量.
一個很顯然的思路是每次都嘗試去在可行的范圍內尋找還未滿載的路徑并使其達到最大流.這樣一條未滿載還可增加流量的路徑稱之為增廣路.每次尋找增廣路這個思路大的方向上是沒有錯的,事實上我們也正是這樣做的.
但是,這樣有一個很顯然的問題,聰明的你一定已經想到了,那就是這會導致加入我們當前得到的可行流中的某一條弧屬于一條更優的路徑,那么這條更優的路徑就會被阻塞而導致無法統計.而如果我們使用一貫的回溯思路來解決,那么復雜度就上升到了指數級,這種復雜度往往難以承受.
首先明確一個事實,從 \(u\) 流向 \(v\) 數值為 \(val\) 的流量 , 再從 \(v\) 流向 \(u\) 數值為 \(value\) 的流量等價于從 \(u\) 流向 \(v\) 的數值為 \(val-value\) 的流量
那么我們就需要一種設計,來使得不通過回溯也能完成所有可行流的統計.由此,我們對于一條弧 \((u,v)\) 建立它的反向弧 \((v,u)\) ,由于一開始并不能有任何的流量從 \(v\) 流向 \(u\) 所以一開始,反向弧的所有容量為0.每當我們正向流過 \(val\) 的流量,對應的反向弧就能反向流動 \(val\) 的流量.這種機制,正是 \(Edmond \: Karp\) 算法和 \(Dinic\) 算法的實現基礎.反向弧的引入使得我們已經流過的流量有了流回來的機會,因此,它代替了回溯的作用.
那么一個非常自然的思路呼之欲出了:每次尋找一條增廣路進行增廣,最后統計出的答案就是最大流!
增廣的過程也十分簡單,把增廣路徑上所有的正向弧容量減去路徑上最大的可行流,反向弧同時增大相應的容量即可
接下來的問題便是尋找增廣路,一個很自然的想法是使用 \(bfs\) 或者 \(dfs\).而我們也確實是這么做的,只不過一般不使用 \(dfs\),它很容易變得很慢,于是我們就選用了喜聞樂見的 \(bfs\) ,穩定的 \(O(n)\) 復雜度相比較而言十分優秀.
明確了以上思路之后,就能得到一個正確也不太慢的最大流算法了,這就是\(Edmonds \: Karp\) 算法,簡稱 \(EK\) 算法.雖然正確性有了保障,而且也足以應付一些不太刁鉆的數據,但它的復雜度是 \(O(n \times m^2)\) 的,十分的不理想.因此,我們需要一種更加優秀的算法,來保證時間復雜度.
那我們引入一個新算法姑且稱之為Dinic算法.(其實就是叫Dinic算法)
首先,我們對圖按照 \(bfs\) 的層次進行分層,然后,我們每次只考慮增廣最短路.也就是每次考慮下一層的節點能否增廣,并進行增廣.然后用一次 \(dfs\) 走出來這一個阻塞流(阻塞流是指把網絡中的弧增廣到源點和匯點并不連通.) 然后不斷分層并進行增廣.
寫出來就這個樣子:
然后我還加了一個當前弧優化,然鵝在代碼上并沒有什么區別.
最后,介紹一個定理最大流最小割定理:
最大流最小割定理是網絡流理論的重要定理。是指在一個網絡流中,能夠從源點到達匯點的最大流量等于如果從網絡中移除就能夠導致網絡流中斷的邊的集合的最小容量和。即在任何網絡中,最大流的值等于最小割的容量。 ——以上來自百度百科(Wiki上十分鬼畜所以沒用)其實你只需要記住最大流等于最小割就完了,然后剩下的網絡流我就只知道最小費用最大流了,但是我不會,所以不說.
最后的最后,網絡流的題只需要把網絡建出來就做出來了,所以最重要的是模型轉化.
常見的套路就是超級源,超級匯,中間連INF.嗯,就是這樣!
轉載于:https://www.cnblogs.com/Equinox-Flower/p/10633382.html
總結
- 上一篇: 深入理解JVM(8)——类加载的时机
- 下一篇: 协程在Socket上的应用