最大流演算法之一 EK演算法

2021-08-21 06:49:15 字數 1686 閱讀 7995

ek演算法的流程很簡單:

隨意找乙個可行流作為流量網路更新的基礎(一般題目沒有規定可以採用流量為0的可行流)利用bfsb

fs找一條從源點到匯點的可行流路徑

用新找到的可行流路徑更新原有流量網路:先找到該可行流路徑中流量最小邊,然後將該路徑上所有正向邊都減去該最小邊的流量,反向邊都加上該最小邊的流量(想想,為什麼要設反向邊)

不斷重複2和3兩個步驟,直到在第2步的時候找不到一條從源點到匯點的可行流路徑(已經達到最大流的流量網路滿足的特徵是,源點能達到的所有點記作集合s,不能達到的所有點記作集合t,那麼從s到t的所有邊流量都為0,t到s的所有邊的流量之和即為最大流)

反向邊的作用,用乙個詞概括:後悔藥

如果沒有反向邊,那麼我們隨意找到乙個可行流,例如這個:

我們很容易找到乙個可行流:1->2->5->6,流量為2。

到這一步之後我們發現我們無法再進行增廣。

如果這時候我們新增了反向邊,就會是這樣:

那麼通過反向邊,我們可以又找到這麼一條可行流路徑:1->4->5->2->3->6,流量為1.

所以最後的最大流是3。

有了反向邊,我們可以做到這件事情:如果我們發現某一條邊上分配流量過多,不利於最優方案的推出,我們利用反向邊可以反悔。

所以反向邊增大的意義就在於正向邊的流量減小,也就是「退流」。

所以我們可以發現,始終滿足:正向邊流量+反向邊流量=該邊容量

#include

using

namespace

std;

inline

int read()

const

int maxn=10020;

const

int maxm=100020;

const

int inf=1e8;

namespace grapha[maxm<<1];//鄰接表

void insert(int x,int y,int w)//插入邊

void init()

}}using

namespace graph;

namespace flowpre[maxn];

//記錄了某點在某一條可行流中

//它的前驅點和連線它和它的前驅的有向邊的編號

bool vis[maxn];//是否被訪問過

bool bfs()}}

return

false;//找不到

}void ek()//找到最小流量

ans+=flow;//本次增廣收益哈哈哈

for(int i=t;i!=s;i=pre[i].v)

}printf("%d\n",ans);

}}using

namespace flow;

int main()

時間複雜度o(

n×m2

) o(n

×m2)

但是,一般不會更新那麼多次。

一般能處理103103

到104104

規模的網路。

最大流 EK演算法

ek演算法。特別暴力 時間複雜度o v e 2 所以競賽中我們一般用效率更高的dinic演算法 ek演算法核心就是殘量網路圖,殘量指的就是每條路上剩餘的流量。不難發現,只要能在殘量網路圖上找到一條從源點到匯點的路,就能在這一條路上加流量,所加的流量就是在這條路徑上每條邊殘量取個min,一點一點的加就...

最大流 EK演算法

ek演算法是求最大流的一種容易實現 易懂的演算法。ek演算法仍然是乙個基於增廣路的演算法,思路非常簡單。每次從s嘗試找到一條到達t的路徑,路徑上最小的殘留量大於0,那麼我們就可以把這條路上的最小殘留量減去,累加到ans裡。繼續bfs直到找不到位置,此時ans就是最大流。ek增廣路演算法的時間複雜度為...

網路最大流演算法 EK演算法

ek演算法是求網路最大流的最基礎的演算法,也是比較好理解的一種演算法,利用它可以解決絕大多數最大流問題。但是受到時間複雜度的限制,這種演算法常常有tle的風險 還記得我們在介紹最大流的時候提到的求解思路麼?對一張網路流圖,每次找出它的最小的殘量 能增廣的量 對其進行增廣。沒錯,ek演算法就是利用這種...