最大流的目的是將最多的物品從源點s
通過其他點的中轉,運送到匯點t
,每條邊具有能運送物品的上限。從s
運送出來的物品數目等於到達t
的物品數量。
針對圖a
,其中每條邊代表運送物品的上上限,圖b是其乙個可行流(a / b, a是實際運送物品,b是物品上限), 其結果為9
, 但不是最大流11
,這樣的可行流有多個,而最大流就是可行流中最大的那個。
容量:對於一條邊(u,
v)(u,v)
(u,v
), 它的物品上限稱為容量,記做c(u
,v)c(u, v)
c(u,v)
, 而對於不存在的邊c(u
,v)=
0c(u, v) = 0
c(u,v)
=0;流量:對於一條邊(u,
v)(u,v)
(u,v
),它的實際運送的物品稱為流量,記做 f(u
,v)f(u, v)
f(u,v)
,而對於不存在的邊f(u
,v)=
0f(u, v) = 0
f(u,v)
=0;殘量:每條邊上的容量和流量的差值。
在最大流問題中,容量c
cc和流量f
ff滿足三個性質:
殘量圖中邊的權修改為殘量,(u,
v)(u, v)
(u,v
) 的殘量我們記做 r(u
,v)r(u, v)
r(u,v)
,並引入反向邊的殘量(其目的是為了可以回退流量)。如下圖:
其中對某條邊進行說明:
r (s
,a)=
c(s,
a)−f
(s,a
)=10−
2=8r(s, a) = c(s, a) - f(s, a) = 10 - 2 = 8
r(s,a)
=c(s
,a)−
f(s,
a)=1
0−2=
8;r (a
,s)=
c(a,
s)−f
(a,s
)=0−
(−2)
=2r(a, s) = c(a, s) - f(a, s) = 0 - (- 2) = 2
r(a,s)
=c(a
,s)−
f(a,
s)=0
−(−2
)=2殘量圖中任何一條從s
ss到t
tt的有向道路都對應這一條原圖中的增廣路,只要求出該道路上的所有殘量的最小值d
dd,把增廣路上的邊流量均增加d
dd即可,這個過程稱為增廣。只要殘量圖中存在增廣路,流量就可以增大。如果殘量圖中不存在增廣路,則當前流量就是最大流。
ek
演算法使用的是bfs
的方式在殘量圖中不斷尋找增廣路。並用p
陣列儲存記錄曾廣路上弧,a
陣列記錄可以增加的流。
#include
using
namespace std;
const
int maxn =
10000+5
;// 鄰接表結構
struct edge };
vector edges;
vector<
int> g[maxn]
;int a[maxn]
;/* 起點到aa的可改進量*/
int p[maxn]
;/* 最短路樹上的入弧編號*/
// 向鄰接表中新增邊, 增加乙個正向殘量,引入乙個反向殘量
void
addedge
(int from,
int to,
int cap)
// 最大流演算法
intmaxflow
(int s,
int t)
}// 找到了增廣路
if(a[t]
)break;}
// 找不到增廣路if(
!a[t]
)break
;// 更新殘量圖
for(
int u = t; u != s; u = edges[p[u]
].from)
flow +
= a[t];}
return flow;
}
最大流 EK演算法
ek演算法。特別暴力 時間複雜度o v e 2 所以競賽中我們一般用效率更高的dinic演算法 ek演算法核心就是殘量網路圖,殘量指的就是每條路上剩餘的流量。不難發現,只要能在殘量網路圖上找到一條從源點到匯點的路,就能在這一條路上加流量,所加的流量就是在這條路徑上每條邊殘量取個min,一點一點的加就...
最大流 EK演算法
ek演算法是求最大流的一種容易實現 易懂的演算法。ek演算法仍然是乙個基於增廣路的演算法,思路非常簡單。每次從s嘗試找到一條到達t的路徑,路徑上最小的殘留量大於0,那麼我們就可以把這條路上的最小殘留量減去,累加到ans裡。繼續bfs直到找不到位置,此時ans就是最大流。ek增廣路演算法的時間複雜度為...
最大流EK演算法模板
include ek 演算法。時間複雜度 ve 2 include includeusing namespace std const int maxn 100 const int inf 1 30 1 int g maxn maxn int flow maxn pre maxn bool vis m...