日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

最大流(Dinic算法)

發布時間:2023/12/20 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 最大流(Dinic算法) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Dinic算法

簡介:

相較 Edmonds-Karp 算法而言,為防止每進行一次增廣,都要做一遍BFS,時間復雜度過高,用于減少所作 BFS 次數。
因而 Dinic 算法在 EK 算法的基礎上增加了分層圖的概念,根據從s到各個點的最短距離的不同,把整個圖分層。

過程:
  • 先利用BFS對殘余網絡分層,一個節點的深度,就是源點到它最少要經過的邊數。
  • 利用BFS對殘余網絡分層,分完層后,利用DFS從前一層向后一層反復尋找增廣路。
    分完層后,從源點開始,用DFS從前一層向后一層反復尋找增廣路(即要求DFS的每一步都必須要走到下一層的節點)。
  • 在分層時,只要進行到匯點的層次數被算出即可停止,因為按照該DFS的規則,和匯點同層或更下一層的節點,是不可能走到匯點的。
  • DFS過程中,要是碰到了匯點,則說明找到了一條增廣路徑。此時要增加總流量的值,消減路徑上各邊的容量,并添加反向邊,即所謂的進行增廣。
  • DFS找到一條增廣路徑后,并不立即結束,而是回溯后繼續DFS尋找下一個增廣路徑。
  • 當最上層的節點如果回溯到源點而且無法繼續往下走了,DFS結束,在此次DFS過程中,可以找到多條增廣路徑。
  • DFS結束后,對殘余網絡再次進行分層,然后再進行DFS當殘余網絡的分層操作無法算出匯點的層次(即BFS到達不了匯點)時,算法結束,最大流求出。
  • 時間復雜度:

    普通情況下, 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算法)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。