最大流問題 EK演算法

2021-10-08 07:33:20 字數 2581 閱讀 1000

最大流的目的是將最多的物品從源點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...