Dinic快速網路流演算法

2021-09-26 05:35:03 字數 1533 閱讀 8436

edmonds-karp演算法,每進行一次增廣,都要做一遍bfs。如果能少做幾次bfs,即可提高效率,dinic演算法可以減少bfs次數。

dinic演算法的關鍵:在一次增廣的過程中,尋找多條增廣路徑。(使用dfs)

先利用bfs對殘餘網路(包括原網路)分層

乙個節點的「層」數,就是源點到它最少要經過的邊數

分完層後,從源點開始,用dfs尋找增廣路,要求dfs的每一步都必須走到下一層的節點。

因此,在前面分層時,只要進行到匯點的層次數被算出即可停止,因為按照該dfs的規則,和匯點同層或更下一層的節點,是不可能走到匯點的。

dfs過程中,若到達匯點,則說明找到了一條增廣路徑。此時要進行增廣。

dfs找到一條增廣路徑後,並不立即結束,而是回溯到某個節點u後繼續dfs尋找下乙個增廣路徑。

節點u滿足以下條件:

(1)dfs搜尋樹的樹邊(u,v)上的容量已經變成0。即剛剛找到的增廣路徑上所增加的流量,等於(u,v)本次增廣前的容量。              (dfs的過程中,是從u走到更下層的v)

(2)u是滿足條件(1)的最上層的節點

如果回溯到源點而且無法繼續往下走,本次dfs結束。

一次dfs的過程中,可以找到多條增廣路徑。dfs結束後,對殘餘網路再次進行分層,然後再dfs。

當殘餘網路的分層操作無法算出匯點的層次(即bfs到達不了匯點)時,演算法結束,最大流求出。

一般用棧實現dfs,這樣就能從棧中提取出增廣路徑。dinic複雜度是n*n*m(n是點數,m是邊數)

問:如何求出最大流中每條邊的流量?

將原圖備份,原圖上的邊的容量減去做完最大流的殘餘網路上的邊的剩餘容量,就是邊的流量。

例:poj 1273 drainage ditches 赤裸裸的網路流問題

#include #include #include using namespace std;

const int inf = 0x3f3f3f3f;

const int maxn = 300;

int g[maxn][maxn];

int visited[maxn];

int layer[maxn];//layer[i]是節點i的層號

int n,m;//m是頂點數目,頂點編號從1開始,1是源,m是匯,n是邊數

bool countlayer()}}

return false;

}int dinic()}}

//增廣,改圖

maxflow+=minc;

for(int i=1;i0&&layer[i]==layer[nd]+1&&!visited[i])

}if(i>m) q.pop_back();}}

}return maxflow;

}int main()

cout<

}return 0;

}

網路流dinic演算法

遇到過不少網路流的題目,直接找增廣路徑的方法時間複雜度實在受不了。常面臨tle的問題。通過學習這個dinic演算法,不僅 短,效率也高。該演算法的重點在於乙個層次圖,是在普通增廣的方法上加了優化,普通的增廣是每次在圖上四處遊蕩,直到找到匯點為止。dinic演算法就是把每個點都給乙個等級level l...

網路流Dinic演算法

我的模板 例題 struct edge edge int llst,int ffrom,int tto,int ccap,int fflow lst llst from from to tto cap ccap flow fflow dinic 演算法有3個重點 乙個是 層次圖 乙個是 阻塞流 乙個...

網路流之Dinic演算法

初學網路流。存一下dinic板子。複雜度o n 2 m uva 1515 pool construction 把每個草地與 s 相連,花費為dig,每個洞與 t 相連,花費為 然後對於每個兩個相鄰的點連一條權值為 build 的邊。求最小割,就是把草和洞分開的花費。因為只有三種割的情況 割s與草之間...