網路流 最大流(Edmond Karp演算法)

2022-05-09 02:42:10 字數 3497 閱讀 7323

一、含義

從源點到經過的所有路徑的最終到達匯點的所有流量和

例如:

在這個圖中求源點1,到匯點4的最大流。答案為50,其中1->2->4為20 ;1->4為20 ;1->2->3->4為10;總和為20+20+10=50。

二、ek演算法的核心

反覆尋找源點s到匯點t之間的增廣路徑,若有,找出增廣路徑上每一段[容量-流量]的最小值delta,若無,則結束。

在尋找增廣路徑時,可以用bfs來找,並且更新殘留網路的值(涉及到反向邊)。

而找到delta後,則使最大流值加上delta,更新為當前的最大流值。

對於bfs找增廣路:

1.     flow[1]=inf,pre[1]=0;

源點1進佇列,開始找增廣路,

capacity[1][2]=40>0,則flow[2]=min(flow[1],40)=40;

capacity[1][4]=20>0,則flow[4]=min(flow[1],20)=20;

capacity[2][3]=30>0,則flow[3]=min(folw[2]=40,30)=30;

capacity[2][4]=30,但是pre[4]=1(已經在capacity[1][4]這遍歷過4號點了)

capacity[3][4].....

當index=4(匯點),結束增廣路的尋找

傳遞歸increasement(該路徑的流),利用前驅pre尋找路徑

路徑也自然變成了這樣:

源點1進佇列,開始找增廣路,

capacity[1][2]=40>0,則flow[2]=min(flow[1],40)=40;

capacity[1][4]=0!>0,跳過

capacity[2][3]=30>0,則flow[3]=min(folw[2]=40,30)=30;

capacity[2][4]=30,pre[4]=2,則flow[2][4]=min(flow[2]=40,20)=20;

capacity[3][4].....

當index=4(匯點),結束增廣路的尋找

傳遞歸increasement(該路徑的流),利用前驅pre尋找路徑

圖也被改成

接下來同理

這就是最終完成的圖,最終sumflow=20+20+10=50(這個就是最大流的值)

ps,為什麼要有反向邊呢?

我們第一次找到了1-2-3-4這條增廣路,這條路上的delta值顯然是1。於是我們修改後得到了下面這個流。(圖中的數字是容量)

這時候(1,2)和(3,4)邊上的流量都等於容量了,我們再也找不到其他的增廣路了,當前的流量是1。

但這個答案明顯不是最大流,因為我們可以同時走1-2-4和1-3-4,這樣可以得到流量為2的流。

那麼我們剛剛的演算法問題在**呢?問題就在於我們沒有給程式乙個」後悔」的機會,應該有乙個不走(2-3-4)而改走(2-4)的機制。那麼如何解決這個問題呢?回溯搜尋嗎?那麼我們的效率就上公升到指數級了。

而這個演算法神奇的利用了乙個叫做反向邊的概念來解決這個問題。即每條邊(i,j)都有一條反向邊(j,i),反向邊也同樣有它的容量。

我們直接來看它是如何解決的:

在第一次找到增廣路之後,在把路上每一段的容量減少delta的同時,也把每一段上的反方向的容量增加delta。即在dec(c[x,y],delta)的同時,inc(c[y,x],delta)

我們來看剛才的例子,在找到1-2-3-4這條增廣路之後,把容量修改成如下

這時再找增廣路的時候,就會找到1-3-2-4這條可增廣量,即delta值為1的可增廣路。將這條路增廣之後,得到了最大流2。

那麼,這麼做為什麼會是對的呢?我來通俗的解釋一下吧。

事實上,當我們第二次的增廣路走3-2這條反向邊的時候,就相當於把2-3這條正向邊已經是用了的流量給」退」了回去,不走2-3這條路,而改走從2點出發的其他的路也就是2-4。(有人問如果這裡沒有2-4怎麼辦,這時假如沒有2-4這條路的話,最終這條增廣路也不會存在,因為他根本不能走到匯點)同時本來在3-4上的流量由1-3-4這條路來」接管」。而最終2-3這條路正向流量1,反向流量1,等於沒有流量。

這就是這個演算法的精華部分,利用反向邊,使程式有了乙個後悔和改正的機會。而這個演算法和我剛才給出的**相比只多了一句話而已。

至此,最大流edmond-karp演算法介紹完畢。

三、**:

/*

poj1273

*/#include

#include

#include

#include

#include

#include

#include

#define io ios::sync_with_stdio(false);\cin.tie(

0);\

cout.tie(0);

using

namespace

std;

const

int max=1000000

;int map[205][205],flow[205],pre[205

],n,m;

bool vis[205

];int

bfs()}}

if(!vis[n]||n==1

)

return -1

;

return

flow[n];

}int

ek()

}return

maxflow;

}int

main()

printf(

"%d\n

",ek());//

輸出從1到n號點的最大流

}

return0;

}

網路流 最大流

網路流 題記 網路流是最近講過的最迷演算法 網路流 network flows 是一種模擬水流的解決問題方法,與線性規劃密切相關。非常重視選手在網路流上的建模技巧,畫圖是非常關鍵的。1 最大流 問題引入 有n條溝渠,與水坑s t相連,匯聚成m個點,第i條溝渠的水流的流量為c i 每乙個點的流入量和流...

網路流(最大流)

我們圍繞一道題來講解吧 藍橋杯 演算法訓練 網路流裸題 首先,何為網路流最大流問題?可行流 對於每條路線 u,v 上給定乙個實數f u,v 滿足 0 f u,v c u,v 則稱f u,v 為路線 u,v 的流量。而對於一組具有源點和匯點,且總流出量 總流入量,則稱為網路中的一條可行流。拿例子來說 ...

網路流 最大流

dinic 最大流 head x 從0開始記 這樣便於找反向邊 異或即可 當前弧優化 include include include include include include include define ll long long define ull unsigned long long d...