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演算法就是利用這種...