最大流-最小割算法学习笔记

引言:  在算法中一般存在最大-最小定理。

        1 、最大匹配<==>最小覆盖  

        2、 最大流<==>最小割

最大流-最小割定理理解引自呆欧的形象表达:“多粗的管子,水就最多多大流量”,比如从自来水厂到用水大户工业小区A 能达到的水的最大流量是多大?考虑到可能从水厂到小区有不少到达的水管,那么最大的流量等于拆掉最少最细的水管后水厂不能给小区A 供水的那些水管流量的集合。当然这种说法并不不严谨,因为这里水管不是双向的,而在网络中谈论的信息流却可是是双向的。

       其实最大流-最小割最难的地方在于构图了,还有必须掌握Dinic算法。

       高效的求最大流算法——Dinci算法:

       Dinci算法是基于“层次图”的时间效率优先的最大流算法。

       层次:从源点走到终点的最短路长度。层次图:每次从源点到终点距离最短并且记录了多条增广路径(在找到最短路的过程记录了多条增广路径,因为找最短路径的过程中自然有分叉,有分叉那么增广路径条数不就变多了么)。在dfs遍历的时候必须按照层次走。

      Dinic算法的思想是为了减少增广次数,建立一个辅助网络L,L与原网络G具有相同的节点数,但边上的容量有所不同,在L上进行增广,将增广后的流值回写到原网络上,再建立当前网络的辅助网络,如此反复,达到最大流

      Dinic三步曲:

      1、利用原网络构造层次图,顺便判断原网络还有无增广路。

      2、利用构造的层次图求此次的最大流,若找不到增广路了则算法结束

      3、更新原网络,即增广过程中遇见的边其正边以及逆边的的容量大小。

       重复上述的三步。

 

      模板:

View Code
  1 #include <iostream>

  2 #include <cstdio>

  3 #include <cstring>

  4 #include <queue>

  5 #include <cmath>

  6 #include <algorithm>

  7 using namespace std;

  8 

  9 const int mn=222;

 10 const int mm=10000;

 11 const double oo=999999;

 12 int node, st, sd, edge;

 13 int reach[mm], next[mm];

 14 double flow[mm];

 15 int adj[mn], work[mn], dis[mn], que[mn];

 16 

 17 inline void init(int _node, int _st, int _sd)

 18 {

 19     node=_node, st=_st, sd=_sd;

 20     for(int i=0; i<node; i++)

 21         adj[i]=-1;

 22     edge=0;

 23 }

 24 

 25 inline void addedge(int u, int v, double c1, double c2)

 26 {

 27     reach[edge]=v, flow[edge]=c1, next[edge]=adj[u],adj[u]=edge++;

 28     reach[edge]=u, flow[edge]=c2, next[edge]=adj[v],adj[v]=edge++;

 29 }

 30 

 31 bool bfs()

 32 {

 33     int i,u,v,l,r=0;

 34     for(i=0; i<node; ++i)dis[i]=-1;

 35     dis[que[r++]=st]=0;

 36     for(l=0; l<r; ++l)

 37         for(i=adj[u=que[l]]; i>=0; i=next[i])

 38             if(flow[i]&&dis[v=reach[i]]<0)

 39             {

 40                 dis[que[r++]=v]=dis[u]+1;

 41                 if(v==sd)return 1;

 42             }

 43     return 0;

 44 }

 45 

 46 double dfs(int u,double exp)

 47 {

 48     if(u==sd) return exp;

 49     double  tmp;

 50     for(int &i=work[u],v; i>=0; i=next[i])

 51         if(flow[i]&&dis[v=reach[i]]==dis[u]+1&&(tmp=dfs(v,min(exp,flow[i])))>0)

 52         {

 53             flow[i]-=tmp;

 54             flow[i^1]+=tmp;

 55             return tmp;

 56         }

 57     return 0;

 58 }

 59 

 60 double Dinic()

 61 {

 62     double max_flow=0, flow;

 63     while(bfs())

 64     {

 65         for(int i=0; i<node; i++)   work[i]=adj[i];

 66         while(flow=dfs(st,oo))

 67             max_flow+=flow;

 68     }

 69     return max_flow;

 70 }

 71 

 72 int main()

 73 {

 74     int  n, m, k, T;

 75     cin >> T;

 76     while(T--)

 77     {

 78         scanf("%d%d%d",&n,&m,&k);

 79         init(n+m+2,0,n+m+1);

 80         double val;

 81         for(int i=1; i<=n; i++)

 82         {

 83             scanf("%lf",&val);

 84             addedge(st,i,log(val),0);

 85         }

 86         for(int i=1; i<=m; i++)

 87         {

 88             scanf("%lf",&val);

 89             addedge(i+n,sd,log(val),0);

 90         }

 91         while(k--)

 92         {

 93             int u, v;

 94             scanf("%d%d",&u,&v);

 95             addedge(u,v+n,oo,0);

 96         }

 97         double ans=Dinic();

 98         printf("%.4lf\n",exp(ans));

 99     }

100     return 0;

101 }

 

        

你可能感兴趣的:(学习笔记)