網路流 Edmond Karp演算法 Dinic演算法

2022-05-16 05:40:54 字數 3540 閱讀 9173

**:網路流基礎篇——edmond-karp演算法             by奈米黑客

通常可以把這些邊想象成道路,流量就是這條道路的車流量,容量就是道路可承受的最大的車流量。很顯然的,流量<=容量。而對於每個不是源點和匯點的點來說,可以模擬的想象成沒有儲存功能的貨物的中轉站,所有「進入」他們的流量和等於所有從他本身「出去」的流量。

求解思路:

首先,假如所有邊上的流量都沒有超過容量(不大於容量),那麼就把這一組流量,或者說,這個流,稱為乙個可行流

乙個最簡單的例子就是,零流,即所有的流量都是0的流。

補充:

為什麼要增加反向邊?

在做增廣路時可能會阻塞後面的增廣路,或者說,做增廣路本來是有個順序才能找完最大流的。

但我們是任意找的,為了修正,就每次將流量加在了反向弧上,讓後面的流能夠進行自我調整。

舉例:比如說下面這個網路流模型

我們第一次找到了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。

c[x,y]-=delta;
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,等於沒有流。

附上自己寫的emonks_karp:

1 #include2 #include3 #include4 #include5 #include6

using

namespace

std;78

const

int inf=0xf777;9

const

int maxn=1000;10

11int

n,m,ans;

12int

vis[maxn],pre[maxn];

13int

mp[maxn][maxn];

1415

bool bfs(int s,int

t)1633}

34return

false;35

}3637int edmonds_karp(int s,int

t)38

50 ans+=minn;51}

52return

ans;53}

5455

intmain()

5664 printf("

%d",edmonds_karp(1

,n));

65return0;

66 }

dinic演算法:

dinic演算法引入了乙個叫做分層圖的概念。具體就是對於每乙個點,我們根據從源點開始的bfs序列,為每乙個點分配乙個深度,然後我們進行若干遍dfs尋找增廣路,每一次由u推出v必須保證v的深度必須是u的深度+1。

1 #include2 #include3 #include4 #include5

using

namespace

std;67

const

int inf=0x7f7f7f7f;8

const

int maxn=400000;9

10struct

edge

11e[maxn];

14int

node,head[maxn],dis[maxn];

15int

s,t;

16int

n,m,ans;

1718

void insert(int u,int v,int

w)19

;21 head[u]=node;

22 e[++node]=(edge);

23 head[v]=node;24}

2526

bool

bfs()

2741}42

return dis[t]!=-1;43

}4445int dfs(int x,int

flow)

4658}59

return0;

60}6162

void

dinic()

6366

67int

main()

6876

dinic();

77 printf("%d"

,ans);

78return0;

79 }

網路流Edmond Karp演算法

前陣子都在忙php的事,沒有時間去更新部落格,今天下午終於狠下心來學網路流,在這裡講一下網路流edmond karp演算法的基礎內容。其思想是不斷通過bfs尋找一條增廣路,直到殘留網路中不再存在增廣路為止。對於每次找到一條增廣路,我們需要知道兩條資訊。1 該增廣路的最大流量 可以定義乙個變數來求得 ...

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

一 含義 從源點到經過的所有路徑的最終到達匯點的所有流量和 例如 在這個圖中求源點1,到匯點4的最大流。答案為50,其中1 2 4為20 1 4為20 1 2 3 4為10 總和為20 20 10 50。二 ek演算法的核心 反覆尋找源點s到匯點t之間的增廣路徑,若有,找出增廣路徑上每一段 容量 流...

最大流(一) Edmond Karp演算法

ek演算法為最短增廣路演算法,具體步驟 1 初始化網路中所有邊的容量 c u v 為該邊的容量,同時反向邊 c v u 為0,初始化最大流為0。2 在殘留網路中找一條從源s到匯t的增廣路p。如果能找到,轉步驟 3 如果不能找到,則轉步驟 5 3 在增廣路p中找到所謂的 瓶頸 邊,即路徑中的最小邊,記...