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


    求网络流有很多算法,这几天学习了两种,记录一下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是一道可以作为模板题目练手。

    模板代码:

      1. #include <cstdio>  
      2. #include <cstring>  
      3. #include <iostream>  
      4. #include <string>  
      5. #include <algorithm>  
      6. #include <map>  
      7. #include <vector>  
      8. using namespace std;  
      9. const int N = 1100;  
      10. const int INF = 0x3f3f3f3f;  
      11.   
      12. struct Node  
      13. {  
      14.     int to;//终点  
      15.     int cap; //容量  
      16.     int rev;  //反向边  
      17. };  
      18.   
      19. vector<Node> v[N];  
      20. bool used[N];  
      21.   
      22. void add_Node(int from,int to,int cap)  //重边情况不影响  
      23. {  
      24.     v[from].push_back((Node){to,cap,v[to].size()});  
      25.     v[to].push_back((Node){from,0,v[from].size()-1});  
      26. }  
      27.   
      28. int dfs(int s,int t,int f)  
      29. {  
      30.     if(s==t)  
      31.         return f;  
      32.     used[s]=true;  
      33.     for(int i=0;i<v[s].size();i++)  
      34.     {  
      35.         Node &tmp = v[s][i];  //注意  
      36.         if(used[tmp.to]==false && tmp.cap>0)  
      37.         {  
      38.             int d=dfs(tmp.to,t,min(f,tmp.cap));  
      39.             if(d>0)  
      40.             {  
      41.                 tmp.cap-=d;  
      42.                 v[tmp.to][tmp.rev].cap+=d;  
      43.                 return d;  
      44.             }  
      45.         }  
      46.     }  
      47.     return 0;  
      48. }  
      49.   
      50. int max_flow(int s,int t)  
      51. {  
      52.     int flow=0;  
      53.     for(;;){  
      54.         memset(used,false,sizeof(used));  
      55.         int f=dfs(s,t,INF);  
      56.         if(f==0)  
      57.             return flow;  
      58.         flow+=f;  
      59.     }  
      60. }  
      61. int main()  
      62. {  
      63.     int n,m;  
      64.     while(~scanf("%d%d",&n,&m))  
      65.     {  
      66.         memset(v,0,sizeof(v));  
      67.         for(int i=0;i<n;i++)  
      68.         {  
      69.             int x,y,z;  
      70.             scanf("%d%d%d",&x,&y,&z);  
      71.             add_Node(x,y,z);  
      72.         }  
      73.         printf("%d ",max_flow(1,m));  
      74.     }  
      75. }  
  • 相关阅读:
    好看的WEB配色..留的美化界面用..
    为phpcms v9 后台增加按类别查找的功能,且不影响升级。
    OS开发过程中常用开源库
    stanford《Developing Apps for ios》第五课demo要点
    C语言简陋的播放mp3代码
    编译ffmpeg for iOS,并调试iFrameExtractor demo
    windows下配置nginx pathinfo模式,支持thinkphp
    初学GTK+2.0与glade的一些网络资源
    在Centos6.3中桥接方式配置vm virtualbox中的系统网络
    Foundation的基本操作—字符串、数组、字典、集合
  • 原文地址:https://www.cnblogs.com/bendantuohai/p/4585331.html
Copyright © 2020-2023  润新知