最大流(Dinic算法)
生活随笔
收集整理的這篇文章主要介紹了
最大流(Dinic算法)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Dinic算法
簡介:
相較 Edmonds-Karp 算法而言,為防止每進行一次增廣,都要做一遍BFS,時間復雜度過高,用于減少所作 BFS 次數。
因而 Dinic 算法在 EK 算法的基礎上增加了分層圖的概念,根據從s到各個點的最短距離的不同,把整個圖分層。
過程:
分完層后,從源點開始,用DFS從前一層向后一層反復尋找增廣路(即要求DFS的每一步都必須要走到下一層的節點)。
時間復雜度:
普通情況下, Dinic算法時間復雜度為O(V2E)
在二分圖中, Dinic算法時間復雜度為O(√VE)
模板題:Drainage Ditches
題意:
n 是農夫約翰挖的溝的數量, m 是這些溝渠的交叉點數量,
交叉口 1 是池塘,交叉點 M 是河流。
水從這條溝從 si 號流到 ei 號, ci 是水流通過溝渠的最大速率。
求水渠中所能流過的水的最大容量。
代碼:
#include<iostream> #include<string.h> #include<queue> #include<cmath> using namespace std; #define INF 0x3f3f3f3f const int MAX=210; struct node {int c;//速率int f;//逆流量 }; int sx,ex;//sx和ex分別代表源點和匯點 int pre[MAX];//前驅 node map[MAX][MAX]; int n,m; bool BFS()//BFS搜索層次網絡 {memset(pre,0,sizeof(pre));queue<int> q;q.push(sx);pre[sx]=1;while(!q.empty()){int start=q.front();q.pop();for(int i=1;i<=n;i++){if(!pre[i]&&map[start][i].c-map[start][i].f){pre[i]=pre[start]+1;q.push(i);}}}return pre[ex]!=0;} int dinic(int pos,int flow)//pos是頂點號,flow是當前頂點所能得到的流量 {int f=flow;if(pos==ex)return flow;for(int i=1;i<=n;i++){if(map[pos][i].c-map[pos][i].f&&pre[pos]+1==pre[i]){int use=map[pos][i].c-map[pos][i].f;//可用水量int t=dinic(i,min(use,flow));map[pos][i].f+=t;map[i][pos].f-=t;flow-=t;//此頂點得到的流量減去改變量}}return f-flow;} int slove() {int sum=0;while(BFS()){sum+=dinic(sx,INF);}return sum; } int main() {int u,v,w;while(cin>>m>>n){sx=1;ex=n;memset(map,0,sizeof(map)) ;for(int i=1;i<=m;i++){cin>>u>>v>>w;map[u][v].c+=w;}cout<<slove()<<endl;}return 0; }ISAP算法
簡介:
同樣是基于分層思想的最大流算法,而有所不同的是,它省去了 Dinic 每次增廣后需要重新構建分層圖的麻煩,而是在每次增廣完成后自動更新每個點的標號。(也就是所在的層)
未結束,待更新
參考:[網絡流]學習筆記:一次理解網絡流!
總結
以上是生活随笔為你收集整理的最大流(Dinic算法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算判断两条线是否垂直,平行,相交,求相
- 下一篇: java中文乱码decode_Java中