網路流最大流 EK演算法

2022-09-08 19:09:12 字數 3806 閱讀 4265

網路流是模仿水流解決生活中類似問題的一種方法策略,來看這麼乙個問題,有乙個自來水廠s,它要向目標t提供水量,從s出發有不確定數量和方向的水管,它可能直接到達t或者經過更多的節點的中轉,目前確定的是每條水管中水流的流向是確定的(單向),且每個水管單位時間內都有屬於自己的水流量的上限(超過會爆水管),問題是求終點t單位時間內獲得的最大水流量是多少?如下圖:

1. 首先,我們用正常的思路去解決這個問題,對於上圖的情況而言,我們可以先選擇一條水流的路線1->2->4,而且我們得知1->2水管水流量上限為40,而2->4水管水流量上限只有20,則這一條路徑通往終點t的水流最大值為20,而這麼走的話,1->2的水管中剩餘水流量則為40-20=20,2->4水管中的剩餘水量為20-20=0,注意:這裡水管剩餘流量為0後說明這條路徑就再也不能接通了,或者說它已經被完全占用了,此時終點t單位時間獲得水量0+20=20

2. 然後我們繼續選擇一條不包含0流量的從s到t的路徑,比如1->2->3->4,此時1->2上水流量剩餘20,2->3剩餘30,3->4剩餘10,很顯然這條路徑上最終能為終點t提供的單位時間的水量由路徑上的最小剩餘流量10決定(就像是木桶的短板效應一樣),這麼走的話,1->2水管中剩餘的水量為40-20-10=10,2-3水管中剩餘的水量為30-10=20,3->4水管中剩餘的水量為10-10=0,它也被完全占用了,此時終點t單位時間獲得水量為20+10=30

3. 我們繼續找還能找到一條從s流向t的路徑1->4,水流上限20,因為是直達的,所以路徑上最小剩餘流量就是它本身,則這麼走的話,1->4上的水流量全部耗盡,20-20=0,它也完全被占用了,而終點t再一次獲得20水量,30+20=50,至此整張網路流圖再也找不到一條能從s到t的不包含0流量的通路,終點t單位時間獲得的最大水流也計算出來得到50

如下圖:如果我們第一次選擇的是1->2->3->4這條路徑(這很符合程式設計的觀念,計算機很容易就按照序號去查詢),那麼1->2水管剩餘流量為1-1=0,2->3水管剩餘流量為1-1=0,3->4水管的剩餘流量為1-1=0,至此我們發現所有的通路都被這三個0流量的水管阻斷了,而此時終點t獲得的單位水量只有0+1=1

按正常的人為的思路,此時我想要反悔之前選的那條路徑,同時選擇別的路徑,而下圖的1->2->4和1->3->4這兩條路徑的選擇才是這張網路流圖的最優選擇,終點t得到的最大水量為1+1=2,而2->3的這條水管我們放棄不用

上述反悔的過程在我們的思維看來確實可以(假裝)沒有走過2->3這條路,但是計算機並不能這麼去主動理解這種情況,它應該按並不是最優的情況去嘗試,當遇到可能更優的情況時更改之前的選擇,在我們設計程式的時候,如何能做到這個反悔的過程呢,關鍵來了:我們對於每次選擇的一條道路上的每個水管都要減去路徑上的最小殘量的同時,為這兩個相鄰的點新增一條反向弧,反向弧的數值加上最小殘量的數值,如上上圖那個並不是最優的走法,假設計算機確實第一次就選擇了這條路徑,那麼我們做出如下處理:1->2剩餘流量依舊為1-1=0,而同時新增一條2->1的反向弧,流量為0+1=1(反向弧也是一條通路,它的存在就像是為我們提供了乙個返回的機會),2->3剩餘流量為1-1=0,新增3->2的反向弧,剩餘流量為0+1=1,同樣3->4的剩餘流量為1-1=0,而4->3的反向弧上的剩餘流量為0+1=1,所以本次選擇之後終點t依舊獲得了1的單位流量

接下來我們繼續選擇一條路徑,1->3->2->4(當然也只剩下這條了),此時我們如上述操作,為1->3剩餘流量,3->2剩餘流量,2->4剩餘流量都減去這條路徑上的最小殘量1,同時為它們兩兩之間的反向弧增加上這個最小殘量1(圖可能有點亂,但是原理是不變的,實線方向-,虛線方向+),至此,1->2=0,2->1=1,1->3=0,3->1=1,2->3=1,3->2=0,2->4=0,4->2=1,3->4=0,4->3=1,從s到t已經沒有一條額外的路徑不包含0流量了,此時t獲得最大單位水量2,並且通過這種建立反向弧的方式,我們對於從2到3再從3到2都走了一遍,這不就好像是模擬了一遍反悔的過程嗎(具體證明這裡不作詳述),接下來講解ek演算法

別著急在講解ek之前我們需要介紹幾個網路流中最重要的概念,我們稱起點s,也就是水流的出發點為源點,將水流的終點t稱為匯點,而我們每一次找一條從源點到匯點的不包含0流量的路徑稱為增廣路,(增廣路顧名思義,如果能找到一條從s到t的增廣路,則到終點的水流量一定還可以增加至少1,所以就滿足了增廣這個要求了),其實求網路流最大流的問題的各個演算法都是在模擬乙個找尋增廣路的過程,如果找不到了就說明此時終點獲得的水量將無法變得更大,答案就算出來了

這裡推薦一題網路流最大流的模板題,poj1273,題面講的是有n個水管,有m個點,源點為1,匯點為m,求匯點t單位時間的最大水流量,當然這題有個小坑,就是輸入會重複,如果1->2 40代表從1流向2有40流量,那可能會有多次1->2 40,1->2 30之類的,要累加成1->2 70

**:

1 #include2 #include3 #include4 #include

5using

namespace

std;67

const

int n = 205;8

const

int inf = 0x3f3f3f3f;9

int c[n][n]; //

記錄i到j的剩餘流量

10int p[n]; //

p[i]記錄流向i點的前驅節點

11int v[n]; //

記錄在一條增廣路中,流到i點時,此刻增廣路上殘餘量的最小值,直到i == m時就是整條增廣路上的殘餘量最小值

12int

n, m;

1314

int min(int a, int

b)17

18void

ek()

39} 40}

41if(v[m] == 0) break; //

如果v[m]==0則代表找不到增廣路了(中途出現了c[i][j]==0的情況)

42 ans +=v[m];

43int temp =m;

44while(p[temp] != 0)

49}

50 printf("

%d\n

", ans); 51}

5253

intmain()

61ek(); 62}

63return0;

64 }

網路流 最大流演算法之EK

首先是網路流中的一些定義 v表示整個圖中的所有結點的集合.e表示整個圖中所有邊的集合.g v,e 表示整個圖.s表示網路的源點,t表示網路的匯點.對於每條邊 u,v 有乙個容量c u,v c u,v 0 如果c u,v 0,則表示 u,v 不存在在網路中。相反,如果原網路中不存在邊 u,v 則令c ...

網路流之最大流演算法模板EK

include include include include using namespace std int maxdata 0x7fffffff int capacity 200 200 c 1000 1000 c i j 儲存初值,因為每次計算都會改變capacity i j 的值,capac...

網路流一 最大流EK演算法(bfs)

poj 1273 網路流最大流ek演算法 時間複雜度上限為nm 2 include include include include using namespace std define maxn 0x7fffffff int n,m int gra 210 210 int pre 210 int f...