zoukankan      html  css  js  c++  java
  • 网络流小结

    网络流主要包括:

    1、最大流

    2、费用流

    3、有上下界的网络流

     

    网络流的基本技巧:

    1、多个源点和汇点的情况。建立超级源点和超级汇点。

    2、顶点有容量限制。拆成两个点,此两点连边,容量为原来的点被限制的容量。

    3、最大费用转为最小费用。变负数,最后变回来。

     

    一、最大流

    最大流算法的思想是不断地找ST的增广路。算法的效率是由找增广路的方法决定的。

    Edmond - Karp算法:用广搜找增广路,时间复杂度 O (n*m*m )。思路最简单。

     

     1 const int N=110, INF=0x3f3f3f3f;
     2 int Map[N][N],pre[N],n,ans;
     3 bool vis[N];
     4 queue<int> que;
     5 bool EK_bfs(int s,int e)
     6 {
     7     int i,k;
     8     while(!que.empty()) que.pop();
     9     memset(vis,0,sizeof(vis));
    10     memset(pre,0,sizeof(pre));
    11     que.push(s);
    12     vis[s]=1;
    13     while(!que.empty())
    14     {
    15         k=que.front();
    16         if(e==k)  return 1;
    17         que.pop();
    18         for(i=1;i<=n;i++)
    19         {
    20             if(Map[k][i]&&!vis[i])
    21             {
    22                 vis[i]=1;
    23                 pre[i]=k;
    24                 que.push(i);
    25             }
    26         }
    27     }
    28     return 0;
    29 }
    30 void EK(int s,int e)
    31 {
    32     int u,mn;
    33     ans=0;
    34     while(EK_bfs(s,e))
    35     {
    36         mn=INF;
    37         u=e;
    38         while(pre[u]!=-1)
    39         {
    40             mn=min(mn,Map[pre[u]][u]);
    41             u=pre[u];
    42         }
    43         ans+=mn;
    44         u=e;
    45         while(pre[u]!=-1)
    46         {
    47             Map[pre[u]][u]-=mn;
    48             Map[u][pre[u]]+=mn;
    49             u=pre[u];
    50         }
    51     }
    52 }
    53 void init()
    54 {
    55     memset(Map,0,sizeof(Map));
    56 }
    View Code

    SAP算法:在寻找增广路的时候用了允许弧,并且用了Dinic算法的优化。时间复杂度为O(m*n*n)

     1 const int N=110;
     2 const int M=2*N*N, INF=0x3f3f3f3f;
     3 struct node
     4 {
     5     int to,next,w;
     6 }edge[M];
     7 int head[N],numh[N],h[N],cure[N],pre[N];
     8 //numh:GAP优化的统计高度数量数组; h:距离标号数组; cure:当前弧
     9 int ans,tot;
    10 void SAP(int s, int e,int n)
    11 {
    12     int flow,u,tmp,neck,i;
    13 ans=0;
    14 memset(pre,-1,sizeof(pre));
    15     memset(h,0,sizeof(h));
    16     memset(numh,0,sizeof(numh));
    17     for(i=1;i<=n;i++)
    18         cure[i]=head[i];
    19     numh[0]=n;
    20     u=s;
    21     while(h[s]<n)
    22     {
    23         if(u==e)
    24         {
    25             flow =INF;
    26             for(i=s;i!=e;i=edge[cure[i]].to)
    27             {
    28                 if(flow>edge[cure[i]].w)
    29                 {
    30                     neck=i;
    31                     flow =edge[cure[i]].w;
    32                 }
    33             }
    34             for(i=s;i!=e;i=edge[cure[i]].to)
    35             {
    36                 tmp=cure[i];
    37                 edge[tmp].w-=flow;
    38                 edge[tmp^1].w+=flow;
    39             }
    40             ans+=flow;
    41             u=neck;
    42         }
    43         for(i=cure[u];i!=-1;i=edge[i].next)
    44             if(edge[i].w && h[u]==h[edge[i].to]+1) break;
    45         if(i!=-1) {cure[u]=i;pre[edge[i].to]=u;u=edge[i].to;}
    46         else
    47         {
    48             if(0==--numh[h[u]]) break; //GAP优化
    49             cure[u]=head[u];
    50             for(tmp=n,i=head[u];i!=-1;i=edge[i].next)
    51                 if(edge[i].w) tmp=min(tmp, h[edge[i].to]);
    52             h[u]=tmp+1;
    53             ++numh[h[u]];
    54             if(u!=s) u=pre[u];
    55         }
    56     }
    57 }
    58 void init()
    59 {
    60     tot=0;
    61     memset(head,-1,sizeof(head));
    62 }
    63 void addedge(int i,int j,int w)
    64 {
    65     edge[tot].to=j;edge[tot].w=w;edge[tot].next=head[i];head[i]=tot++;
    66     edge[tot].to=i;edge[tot].w=0;edge[tot].next=head[j];head[j]=tot++;
    67 }
    View Code

    Dinic算法:时间复杂度为O(m*n*n)

     1 const int N=110;
     2 const int M=2*N*N, INF=0x3f3f3f3f;
     3 struct node
     4 {
     5     int to,next,w;
     6 }edge[M];
     7 int level[N],que[N],head[N];
     8 int tot,ans;
     9 bool makelevel(int s, int t)
    10 {
    11     memset(level,0,sizeof(level));
    12     level[s]=1;
    13     int iq=0 , i, k, top;
    14     que[iq++]=s;
    15     for(i=0;i<iq;i++)
    16     {
    17         top=que[i];
    18         if(top==t) return 1;
    19         for(k=head[top];k!=-1;k=edge[k].next)
    20             if(!level[edge[k].to] && edge[k].w)
    21             {
    22                 que[iq++]=edge[k].to;
    23                 level[edge[k].to]=level[top]+1;
    24             }
    25     }
    26     return 0;
    27 }
    28 int DFS(int now, int maxf, int t)
    29 {
    30     if(now ==t) return maxf;
    31     int ret=0, f, k;
    32     for(k=head[now];k!=-1;k=edge[k].next)
    33     {
    34         if(edge[k].w && level[edge[k].to]==level[now]+1)
    35         {
    36             f=DFS(edge[k].to, min(maxf-ret,edge[k].w), t);
    37             edge[k].w-=f;
    38             edge[k^1].w+=f;
    39             ret+=f;
    40             if(ret==maxf) return ret;
    41         }
    42     }
    43     return ret;
    44 }
    45 void DINIC(int s, int t)
    46 {
    47     ans=0;
    48     while(makelevel(s,t)) ans+=DFS(s,INF,t);
    49 }
    50 void init()
    51 {
    52     tot=0;
    53     memset(head,-1,sizeof(head));
    54 }
    55 void addedge(int i,int j,int w)
    56 {
    57     edge[tot].to=j;edge[tot].w=w;edge[tot].next=head[i];head[i]=tot++;
    58     edge[tot].to=i;edge[tot].w=0;edge[tot].next=head[j];head[j]=tot++;
    59 }
    View Code

    个人体会:最大流的题目一般不要求对算法进行修改(模版),难点在于如何把问题转为最大流问题,建图是一个难点。巧妙的建图可以把点的数量减少,从而减少时间复杂度。有一个文档叫网络流建模汇总,做得非常好。

    题目链接http://www.cnblogs.com/Potato-lover/category/611621.html

    1、判断满流

    3572  Task Schedule 

    2883  kebab

    2、二分+最大流

    传送门:

    3、最短路+最大流

    3416 Marriage Match IV

     

    二、费用流

    一般情况下都是求最大流条件下的最小费用。

    算法: 连续最短路算法。

    时间复杂度OC*k*m),C是最终的流量,k*m就是SPFA算法的时间复杂度。

     1 const int N =1010, M=50010,INF=0x3f3f3f3f;
     2 struct node
     3 {
     4     int to, next, c ,f;//c是容量,f是费用
     5 }edge[M];
     6 int head[N],dis[N],load[N],p[N];
     7 bool vis[N];
     8 int tot,flow,cost;
     9 bool spfa(int S, int E,int n)
    10 {
    11     int que[N*10],qout,qin;
    12     memset(vis,0,sizeof(vis));
    13     memset(load,-1,sizeof(load));
    14     memset(p,-1,sizeof(p));
    15     for(int i=0;i<=n;i++)
    16         dis[i]=INF;
    17     qin=qout=0;
    18     que[qin++]=S;
    19     dis[S]=0;
    20     vis[S]=1;
    21     while(qin!=qout)
    22     {
    23         int u=que[qout++];
    24         vis[u]=0;
    25         for(int i=head[u];i!=-1;i=edge[i].next)
    26         {
    27             if(edge[i].c)
    28             {
    29                 int v=edge[i].to;
    30                 if(dis[v]-dis[u]>edge[i].f)
    31                 {
    32                     dis[v]=dis[u]+edge[i].f;
    33                     p[v]=u;
    34                     load[v]=i;
    35                     if(!vis[v])
    36                     {
    37                         vis[v]=1;
    38                         que[qin++]=v;
    39                     }
    40                 }
    41             }
    42         }
    43     }
    44     if(dis[E]==INF) return 0;
    45     return 1;
    46 }
    47 void MCF(int S, int E,int n)
    48 {
    49     int u,mn;
    50     flow=cost=0;
    51     while(spfa(S,E,n))
    52     {
    53         u=E; mn=INF;
    54         while(p[u]!=-1)
    55         {
    56             mn=min(edge[load[u]].c, mn);
    57             u=p[u];
    58         }
    59         u=E;
    60         while(p[u]!=-1)
    61         {
    62             edge[load[u]].c-=mn;
    63             edge[load[u]^1].c+=mn;
    64             u=p[u];
    65         }
    66         cost+=dis[E]*mn;
    67         flow+=mn;
    68     }
    69 }
    70 void addedge(int a,int b,int c,int d)
    71 {
    72     edge[tot].to=b;edge[tot].c=c;edge[tot].f=d;
    73     edge[tot].next=head[a];head[a]=tot++;
    74     edge[tot].to=a;edge[tot].c=0;edge[tot].f=-d;
    75     edge[tot].next=head[b];head[b]=tot++;
    76 }
    77 void init()
    78 {
    79     tot=0;
    80     memset(head,-1,sizeof(head));
    81 }
    View Code

     

    题目链接:http://www.cnblogs.com/Potato-lover/category/615756.html

     

    三、有上下界的网络流

    已经做过总结:http://www.cnblogs.com/Potato-lover/p/4002823.html

     

     

  • 相关阅读:
    [hibernate]org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter
    [extjs] extjs 5.1 API 开发 文档
    [java] Unsupported major.minor version 51.0 错误解决方案
    [kfaka] Apache Kafka:下一代分布式消息系统
    [spring] org.objectweb.asm.ClassVisitor.visit(IILjava/lang/String;Ljav 解决
    [spring] 对实体 "characterEncoding" 的引用必须以 ';' 分隔符结尾
    [java] java 中Unsafe类学习
    [java] java 线程join方法详解
    [java] jstack 查看死锁问题
    ORACLE DG之参数详解
  • 原文地址:https://www.cnblogs.com/Potato-lover/p/4008360.html
Copyright © 2011-2022 走看看