網絡流入門


網絡流的最經典應用就是最大流....給定一個圖...給出每條邊能流過的最大流量...求源點到匯點的最大流量....

   求解網絡流的基本思想就是每次尋找增廣路(就是源點到匯點的一條可行路)..然后ans+=增廣路能流過的流量..更新剩余網絡..然后再做增廣路...直到做不出增廣路..關於網絡流入門最難理解的地方就是剩余網絡了....為什么在找到一條增廣路后...不僅要將每條邊的可行流量減去增廣路能流過的流量...還要將每條邊的反向弧加上增廣路能流過的流量.?..原因是在做增廣路時可能會阻塞后面的增廣路...或者說做增廣路本來是有個順序才能找完最大流的.....但我們是任意找的...為了修正...就每次將流量加在了反向弧上...讓后面的流能夠進行自我調整...剩余網絡的更新(就在原圖上更新就可以了):

 

1          while (NowPoint!= 1)
2         {
3             PrePoint=pre[NowPoint];
4             Network[PrePoint][NowPoint]-=MinFlow;
5             Network[NowPoint][PrePoint]+=MinFlow;
6             NowPoint=PrePoint;    

 

7         }


最近又復習了下最大流問題,每次看這部分的內容都會有新的收獲。可以說最大流問題的資料網上一搜一大把,根本沒有必要自己寫;但是大部分資料上的專業術語太多了,初學很難理解,至少我當年學這部分的時候前幾次就沒有看懂。所以我准備備份一點個人的理解。

 

圖-1


 

  如圖-1所示,在這個運輸網絡中,源點S和匯點T分別是1,7,各邊的容量為C(u,v)。圖中紅色虛線所示就是一個可行流。標准圖示法如圖-2所示:


 

其中p(u,v) / c(u,v)分別表示該邊的實際流量與最大容量。 

關於最大流

  熟悉了什么是網絡流,最大流也就很好理解了。就是對於任意的uV-{s},使得p(s,u)的和達到最大。上面的運輸網絡中,最大流如圖-3所示:MaxFlow=p(1,2)+p(1,3)=2+1=3。

  在介紹最大流問題之前,先介紹幾個概念:殘余網絡,增廣路徑,反向弧,最大流定理以及求最大流的Ford-Fulkerson方法。

殘余網絡 增廣路徑 反向弧

  觀察下圖-4,這種狀態下它的殘余網絡如圖-5所示:


   

  也許現在你已經知道什么是殘余網絡了,對於已經找到一條從S 到T的路徑的網絡中,只要在這條路徑上,把C(u,v)的值更新為C(u,v)-P(u,v),並且添加反向弧C(v,u)。對應的增廣路徑Path為殘留網絡上從S到T的一條簡單路徑。圖-4中1,2,4,7就是一條增廣路徑,當然還有1,3,4,7。

  此外在未做任何操作之前,原始的有向圖也是一個殘余網絡,它僅僅是未做任何更新而已。

 

最大流定理

  如果殘留網絡上找不到增廣路徑,則當前流為最大流;反之,如果當前流不為最大流,則一定有增廣路徑。

 

Ford-Fulkerson方法

  介紹完上面的概念之后,便可以用Ford-Fulkerson方法求最大流了。為什么叫Ford-Fulkerson方法而不是算法,原因在於可以用多種方式實現這一方法,方式並不唯一。下面介紹一種基於廣度優先搜索(BFS)來計算增廣路徑P的算法:Edmonds-Karp算法。

  算法流程如下:

  設隊列Q:存儲當前未訪問的節點,隊首節點出隊后,成為已檢查的標點;

  Path數組:存儲當前已訪問過的節點的增廣路徑;

  Flow數組:存儲一次BFS遍歷之后流的可改進量;

  Repeat:

    Path清空;

    源點S進入Path和Q,Path[S]<-0,Flow[S]<-+∞;

    While Q非空 and 匯點T未訪問 do

        Begin

            隊首頂點u出對;

            For每一條從u出發的弧(u,v) do

                If v未訪問 and 弧(u,v) 的流量可改進;

                Then Flow[v]<-min(Flow[u],c[u][v]) and v入隊 and Path[v]<-u;

    End while

   

    If(匯點T已訪問)

    Then 從匯點T沿着Path構造殘余網絡;

  Until 匯點T未被訪問

 

 

求解最大流流最原始的算法是Ford_Fulkerson..也就是上面提到的每次找任意的找增廣路...加上增廣路流量再更新剩余網絡...可以看出找最大流最耗時的地方就是尋找增廣路..Edmonds_Karp是對Ford_Fulkerson的一個優化算法...Ford_Fulkerson是任意尋找增廣路...而Edmonds_Karp是每次尋找從源點到匯點可行的最短的增廣路...其優勢是可以在前期就卡斷很多不必要的尋找增廣路而又到不了匯點的過程...其優化的方法也很簡單..就是將Ford_Fulkerson找增廣路的過程用BFS實現..

   一個找最大流更好的優化則是Dinic..優化的地方也是找增廣路的過程....Dinic做了一個預處理...將所有點按到源點的距離分層...然后在尋找增廣路時..只有要拓展點與當前點的距離差為1時才拓展...其原理我還沒弄明白..只知道算法的基本思路...

   Dinic的過程是 : 

       1、BFS做出層次網絡

       2、DFS尋找增廣路

 

CODE:

 1 void Dinic()

2 {
3       while (BFS())
4      {
5          FindARoad= false;
6          DFS( 1, 1,oo);
7      }     
8 }

 

 

 

 

部分轉載自:http://blog.csdn.net/kk303/article/details/6707605 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM