一、含義
從源點到經過的所有路徑的最終到達匯點的所有流量和
例如:
在這個圖中求源點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...