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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

网络流之最大流算法(EdmondsKarp)

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

網絡流之最大流算法(EdmondsKarp)

標簽:?網絡流算法EdmondsKarp流量最大流 ?34795人閱讀?評論(12)?收藏?舉報 ?分類: 圖論~~網絡流(26)?

求網絡流有很多算法,這幾天學習了兩種,記錄一下EK算法。

首先是網絡流中的一些定義:

V表示整個圖中的所有結點的集合.
E表示整個圖中所有邊的集合.
G = (V,E) ,表示整個圖.
s表示網絡的源點,t表示網絡的匯點.
對于每條邊(u,v),有一個容量c(u,v) ? (c(u,v)>=0),如果c(u,v)=0,則表示(u,v)不存在在網絡中。相反,如果原網絡中不存在邊(u,v),則令c(u,v)=0.
對于每條邊(u,v),有一個流量f(u,v).

一個簡單的例子.網絡可以被想象成一些輸水的管道.括號內右邊的數字表示管道的容量c,左邊的數字表示這條管道的當前流量f.


網絡流的三個性質:

1、容量限制: ?f[u,v]<=c[u,v]
2、反對稱性:f[u,v] = - f[v,u]
3、流量平衡: ?對于不是源點也不是匯點的任意結點,流入該結點的流量和等于流出該結點的流量和。
只要滿足這三個性質,就是一個合法的網絡流.

最大流問題,就是求在滿足網絡流性質的情況下,源點 s 到匯點 t 的最大流量。


求一個網絡流的最大流有很多算法 這里首先介紹 增廣路算法(EK)

學習算法之前首先看了解這個算法中涉及到的幾個圖中的定義:


**殘量網絡

為了更方便算法的實現,一般根據原網絡定義一個殘量網絡。其中r(u,v)為殘量網絡的容量。
r(u,v) = c(u,v) – f(u,v)
通俗地講:就是對于某一條邊(也稱弧),還能再有多少流量經過。
Gf
?殘量網絡,Ef?表示殘量網絡的邊集.


這是上面圖的一個殘量網絡。殘量網絡(如果網絡中一條邊的容量為0,則認為這條邊不在殘量網絡中。

r(s,v1)=0,所以就不畫出來了。另外舉個例子:r(v1,s) = c(v1,s) – f(v1,s) = 0 – (-f(s,v1)) = f(s,v1) = 4.

其中像(v1,s)這樣的邊稱為后向弧,它表示從v1到s還可以增加4單位的流量。

但是從v1到s不是和原網絡中的弧的方向相反嗎?顯然“從v1到s還可以增加4單位流量”這條信息毫無意義。那么,有必要建立這些后向弧嗎?

顯然,第1個圖中的畫出來的不是一個最大流。

但是,如果我們把s -> v2 -> v1 -> t這條路徑經過的弧的流量都增加2,就得到了該網絡的最大流。

注意到這條路徑經過了一條后向弧:(v2,v1)。

如果不設立后向弧,算法就不能發現這條路徑。

**從本質上說,后向弧為算法糾正自己所犯的錯誤提供了可能性,它允許算法取消先前的錯誤的行為(讓2單位的流從v1流到v2)

注意,后向弧只是概念上的,在程序中后向弧與前向弧并無區別.


**增廣路

增廣路定義:在殘量網絡中的一條從s通往t的路徑,其中任意一條弧(u,v),都有r[u,v]>0。


如圖綠色的即為一條增廣路。

看了這么多概念相信大家對增廣路算法已經有大概的思路了吧。


**增廣路算法

增廣路算法:每次用BFS找一條最短的增廣路徑,然后沿著這條路徑修改流量值(實際修改的是殘量網絡的邊權)。當沒有增廣路時,算法停止,此時的流就是最大流。


**增廣路算法的效率

設n = |V|, ?m = |E|

每次增廣都是一次BFS,效率為O(m),而在最壞的情況下需要(n-2增廣。(即除源點和匯點外其他點都沒有連通,所有點都只和s與t連通)

所以,總共的時間復雜度為O(m*n),所以在稀疏圖中效率還是比較高的。


hdoj 1532是一道可以作為模板題目練手。

模板代碼:

[cpp]?view plaincopy print?
  • #include?<cstdio>??
  • #include?<cstring>??
  • #include?<iostream>??
  • #include?<string>??
  • #include?<algorithm>??
  • #include?<map>??
  • #include?<vector>??
  • using?namespace?std;??
  • const?int?N?=?1100;??
  • const?int?INF?=?0x3f3f3f3f;??
  • ??
  • struct?Node??
  • {??
  • ????int?to;//終點??
  • ????int?cap;?//容量??
  • ????int?rev;??//反向邊??
  • };??
  • ??
  • vector<Node>?v[N];??
  • bool?used[N];??
  • ??
  • void?add_Node(int?from,int?to,int?cap)??//重邊情況不影響??
  • {??
  • ????v[from].push_back((Node){to,cap,v[to].size()});??
  • ????v[to].push_back((Node){from,0,v[from].size()-1});??
  • }??
  • ??
  • int?dfs(int?s,int?t,int?f)??
  • {??
  • ????if(s==t)??
  • ????????return?f;??
  • ????used[s]=true;??
  • ????for(int?i=0;i<v[s].size();i++)??
  • ????{??
  • ????????Node?&tmp?=?v[s][i];??//注意??
  • ????????if(used[tmp.to]==false?&&?tmp.cap>0)??
  • ????????{??
  • ????????????int?d=dfs(tmp.to,t,min(f,tmp.cap));??
  • ????????????if(d>0)??
  • ????????????{??
  • ????????????????tmp.cap-=d;??
  • ????????????????v[tmp.to][tmp.rev].cap+=d;??
  • ????????????????return?d;??
  • ????????????}??
  • ????????}??
  • ????}??
  • ????return?0;??
  • }??
  • ??
  • int?max_flow(int?s,int?t)??
  • {??
  • ????int?flow=0;??
  • ????for(;;){??
  • ????????memset(used,false,sizeof(used));??
  • ????????int?f=dfs(s,t,INF);??
  • ????????if(f==0)??
  • ????????????return?flow;??
  • ????????flow+=f;??
  • ????}??
  • }??
  • int?main()??
  • {??
  • ????int?n,m;??
  • ????while(~scanf("%d%d",&n,&m))??
  • ????{??
  • ????????memset(v,0,sizeof(v));??
  • ????????for(int?i=0;i<n;i++)??
  • ????????{??
  • ????????????int?x,y,z;??
  • ????????????scanf("%d%d%d",&x,&y,&z);??
  • ????????????add_Node(x,y,z);??
  • ????????}??
  • ????????printf("%d\n",max_flow(1,m));??
  • ????}??
  • }??


  • 總結

    以上是生活随笔為你收集整理的网络流之最大流算法(EdmondsKarp)的全部內容,希望文章能夠幫你解決所遇到的問題。

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