zoukankan      html  css  js  c++  java
  • 网络流模板们

    最大流EK:

     1 #include <vector>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define N1 210
     6 #define M1 1010
     7 #define ll long long
     8 #define dd double
     9 #define inf 0x3f3f3f3f
    10 using namespace std;
    11 
    12 int gint()
    13 {
    14     int ret=0,fh=1;char c=getchar();
    15     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    16     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
    17     return ret*fh;
    18 }
    19 
    20 struct Edge{
    21 int head[N1],to[M1<<1],nxt[M1<<1],val[M1<<1],cte;
    22 void ae(int u,int v,int w)
    23 {
    24     cte++; to[cte]=v; val[cte]=w;
    25     nxt[cte]=head[u]; head[u]=cte;
    26 }
    27 }e;
    28 
    29 int que[N1],hd,tl;
    30 int flow[N1],id[N1];
    31 
    32 int bfs(int S,int T)
    33 {
    34     int x,j,v;
    35     memset(flow,0,sizeof(flow));
    36     memset(id,0,sizeof(id));
    37     hd=1,tl=0; que[++tl]=S; flow[S]=inf;
    38     while(hd<=tl)
    39     {
    40         x=que[hd++];
    41         for(j=e.head[x];j;j=e.nxt[j])
    42         {
    43             v=e.to[j]; 
    44             if(id[v]||e.val[j]==0) continue;
    45             flow[v]=min(flow[x],e.val[j]);
    46             id[v]=j; que[++tl]=v;
    47         }
    48     }
    49     if(!flow[T]) return -1;
    50     else return flow[T];
    51 }
    52 
    53 int EK(int S,int T)
    54 {
    55     int x,mxflow=0,tmp;
    56     while(1)
    57     {
    58         tmp=bfs(S,T); 
    59         if(tmp==-1) return mxflow;
    60         for(x=T;x!=S;x=e.to[id[x]^1])
    61         {
    62             e.val[id[x]]-=tmp;
    63             e.val[id[x]^1]+=tmp;
    64         }
    65         mxflow+=tmp;
    66     }
    67 }
    68 
    69 int n,m,S,T;
    70 
    71 int main()
    72 {
    73     scanf("%d%d%d%d",&n,&m,&S,&T);
    74     int i,j,k,x,y,z; e.cte=1;
    75     for(i=1;i<=m;i++){ x=gint(); y=gint(); z=gint(); e.ae(x,y,z); e.ae(y,x,0); }
    76     printf("%d
    ",EK(S,T));
    77     return 0;
    78 }
    View Code

    最大流Dinic:

     1 #include <vector>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define N1 10010
     6 #define M1 100010
     7 #define ll long long
     8 #define dd double
     9 #define inf 0x3f3f3f3f
    10 using namespace std;
    11 
    12 int gint()
    13 {
    14     int ret=0,fh=1;char c=getchar();
    15     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    16     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
    17     return ret*fh;
    18 }
    19 
    20 struct Edge{
    21 int head[N1],to[M1<<1],nxt[M1<<1],val[M1<<1],cte;
    22 void ae(int u,int v,int w)
    23 {
    24     cte++; to[cte]=v; val[cte]=w;
    25     nxt[cte]=head[u]; head[u]=cte;
    26 }
    27 }e;
    28 
    29 int que[N1],hd,tl,dep[N1],now[N1];
    30 int n,m,S,T,mxflow; 
    31 
    32 int bfs()
    33 {
    34     int x,j,v;
    35     memset(dep,-1,sizeof(dep));
    36     memcpy(now,e.head,sizeof(e.head));
    37     hd=1,tl=0; que[++tl]=S; dep[S]=0;
    38     while(hd<=tl)
    39     {
    40         x=que[hd++];
    41         for(j=e.head[x];j;j=e.nxt[j])
    42         {
    43             v=e.to[j];
    44             if(dep[v]!=-1||!e.val[j]) continue;
    45             dep[v]=dep[x]+1; que[++tl]=v;
    46         }
    47     }
    48     if(dep[T]==-1) return 0;
    49     else return 1;
    50 }
    51 
    52 int dfs(int u,int limit)
    53 {
    54     if(!limit||u==T) return limit;
    55     int j,v,flow,ans=0;
    56     for(j=now[u];j;j=e.nxt[j])
    57     {
    58         now[u]=j; v=e.to[j]; 
    59         if(dep[v]==dep[u]+1 && (flow=dfs(v,min(limit,e.val[j]))) )
    60         {
    61             limit-=flow; ans+=flow;
    62             e.val[j]-=flow; e.val[j^1]+=flow;
    63             if(!limit) break;
    64         }
    65     }
    66     return ans;
    67 }
    68 
    69 int Dinic()
    70 {
    71     while(bfs())
    72     {
    73         mxflow+=dfs(S,inf);
    74     }
    75     return mxflow;
    76 }
    77 
    78 
    79 int main()
    80 {
    81     scanf("%d%d%d%d",&n,&m,&S,&T);
    82     int i,x,y,z,ans=0; e.cte=1;
    83     for(i=1;i<=m;i++){ x=gint(); y=gint(); z=gint(); e.ae(x,y,z); e.ae(y,x,0); }
    84     ans=Dinic();
    85     printf("%d
    ",ans);
    86     return 0;
    87 }
    View Code

    费用流spfaEK:

     1 #include <vector>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define N1 5010
     6 #define M1 50010
     7 #define ll long long
     8 #define dd double
     9 #define inf 0x3f3f3f3f
    10 using namespace std;
    11 
    12 int gint()
    13 {
    14     int ret=0,fh=1;char c=getchar();
    15     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    16     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
    17     return ret*fh;
    18 }
    19 
    20 int n,m,S,T;
    21 struct Edge{
    22 int head[N1],to[M1<<1],nxt[M1<<1],val[M1<<1],flow[M1<<1],cte;
    23 void ae(int u,int v,int F,int W)
    24 {
    25     cte++; to[cte]=v; flow[cte]=F; val[cte]=W; 
    26     nxt[cte]=head[u]; head[u]=cte;
    27 }
    28 }e;
    29 
    30 int que[M1<<1],dis[N1],flow[N1],use[N1],id[N1],hd,tl;
    31 
    32 int spfa()
    33 {
    34     int x,j,v;
    35     memset(dis,0x3f,sizeof(dis)); memset(flow,0,sizeof(flow)); memset(use,0,sizeof(use));
    36     hd=1,tl=0; que[++tl]=S; dis[S]=0; use[S]=1; flow[S]=inf;
    37     while(hd<=tl)
    38     {
    39         x=que[hd++];
    40         for(j=e.head[x];j;j=e.nxt[j])
    41         {
    42             v=e.to[j];
    43             if(e.flow[j]>0&&dis[v]>dis[x]+e.val[j])
    44             {
    45                 dis[v]=dis[x]+e.val[j]; id[v]=j;
    46                 flow[v]=min(flow[x],e.flow[j]);
    47                 if(!use[v]) que[++tl]=v,use[v]=1;
    48             }
    49         }
    50         use[x]=0;
    51     }
    52     return dis[T]!=inf;
    53 }
    54 
    55 int mxflow=0,tot_cost=0;
    56 void EK()
    57 {
    58     int x; mxflow=0,tot_cost=0;
    59     while(spfa())
    60     {
    61         mxflow+=flow[T]; tot_cost+=dis[T]*flow[T];
    62         for(x=T;x!=S;x=e.to[id[x]^1])
    63         {
    64             e.flow[id[x]]-=flow[T];
    65             e.flow[id[x]^1]+=flow[T];
    66         }
    67     }
    68 }
    69 
    70 
    71 int main()
    72 {
    73     scanf("%d%d%d%d",&n,&m,&S,&T);
    74     int i,a,b,c,d; e.cte=1;
    75     for(i=1;i<=m;i++)
    76     {
    77         scanf("%d%d%d%d",&a,&b,&c,&d);
    78         e.ae(a,b,c,d); e.ae(b,a,0,-d);
    79     }
    80     EK();
    81     printf("%d %d
    ",mxflow,tot_cost);
    82     return 0;
    83 }
    View Code

    无源汇上下界可行流:

    给定一张图,每条边都有对应的流量限制$[l,r]$,要求每条边的流量都在规定范围内

    我们想办法去掉流量下界的限制,每条边流量上限改成$r-l$,然后跑最大流就行了

    直接去掉是不行的

    假设每条边都流了流量下界l点流量,此时一些点可能并不满足流量守恒

    而我们最终建出来的网络流图中,每个点的出入流量显然是守恒的(除了源汇)

    所以我们把点向源点汇点连边来让它流量守恒

    具体做法是,手动建出源$S$汇$T$

    点$x$的最小入流量$>$最小出流量,$S$向$x$连流量为差值的边,反之$x$向$T$连流量为差值的边

    模拟出原图中流量下界对点的影响

    然后跑最大流,每条边的实际流量=最小割后的流量+流量下界

    如果在最小割图中源汇连出去的边没流满,说明有边的流量下界没达到,一定无解

      1 #include <cmath>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define N1 210
      6 #define M1 40010
      7 #define ll long long
      8 using namespace std;
      9 const int inf=0x3f3f3f3f;
     10 
     11 int gint()
     12 {
     13     int ret=0,fh=1; char c=getchar();
     14     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     15     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     16     return ret*fh;
     17 }
     18 struct Edge{
     19 int to[M1<<1],nxt[M1<<1],flow[M1<<1],val[M1<<1],head[N1],cte;
     20 void ae(int u,int v,int f,int w)
     21 {
     22     cte++; to[cte]=v; nxt[cte]=head[u];
     23     head[u]=cte; flow[cte]=f; val[cte]=w;
     24 }
     25 }e;
     26 
     27 int n,m,S,T,hd,tl;
     28 int dep[N1],cur[N1],que[M1];
     29 
     30 int bfs()
     31 {
     32     int x,j,v;
     33     memset(dep,-1,sizeof(dep)); memcpy(cur,e.head,sizeof(cur));
     34     hd=1,tl=0; que[++tl]=S; dep[S]=0;
     35     while(hd<=tl)
     36     {
     37         x=que[hd++];
     38         for(j=e.head[x];j;j=e.nxt[j])
     39         {
     40             v=e.to[j]; 
     41             if( e.flow[j]>0 && dep[v]==-1 )
     42             {
     43                 dep[v]=dep[x]+1;
     44                 que[++tl]=v;
     45             }
     46         }
     47     }
     48     return dep[T]!=-1;
     49 }
     50 int dfs(int x,int limit)
     51 {
     52     if( (x==T) || (!limit) ) return limit;
     53     int j,v,flow,ans=0;
     54     for(j=cur[x];j;j=e.nxt[j])
     55     {
     56         cur[x]=j; v=e.to[j];
     57         if( (dep[v]==dep[x]+1) && ( flow=dfs(v,min(limit,e.flow[j])) ) )
     58         {
     59             e.flow[j]-=flow; limit-=flow;
     60             e.flow[j^1]+=flow; ans+=flow;
     61             if(!limit) break;
     62         }
     63     }
     64     return ans;
     65 }
     66 int Dinic()
     67 {
     68     int mxflow=0;
     69     while( bfs() )
     70     {
     71         mxflow+=dfs(S,inf);
     72     }
     73     return mxflow;
     74 }
     75 int ouc[N1],id[M1],Flow[M1];
     76 
     77 int main()
     78 {
     79     int i,j,x,y,v,l,r,ans; 
     80     scanf("%d%d",&n,&m); 
     81     S=0,T=n+1; e.cte=1;
     82     for(i=1;i<=m;i++) 
     83     {
     84         x=gint(), y=gint(), l=gint(), r=gint();
     85         e.ae(x,y,r-l,l); id[e.cte]=i; e.ae(y,x,0,l); 
     86         ouc[x]+=l; ouc[y]-=l; 
     87     }
     88     for(x=1;x<=n;x++) 
     89         if(ouc[x]<0) e.ae(S,x,-ouc[x],0), e.ae(x,S,0,0);
     90         else e.ae(x,T,ouc[x],0), e.ae(T,x,0,0);
     91     ans=Dinic();
     92     for(j=e.head[S];j;j=e.nxt[j])
     93     {
     94         v=e.to[j];
     95         if(e.flow[j]>0){ puts("NO"); return 0; }
     96     }
     97     for(j=e.head[T];j;j=e.nxt[j])
     98     {
     99         v=e.to[j]; 
    100         if(e.flow[j^1]>0){ puts("NO"); return 0; }
    101     }
    102     puts("YES");
    103     for(x=1;x<=n;x++)
    104     for(j=e.head[x];j;j=e.nxt[j])
    105     {
    106         v=e.to[j];
    107         if(!(j&1)) Flow[id[j]]=e.flow[j^1]+e.val[j];
    108     }
    109     for(i=1;i<=m;i++)
    110         printf("%d
    ",Flow[i]);
    111     return 0;
    112 }
    View Code

    有源汇上下界最大流:

    给定一张有源汇网络流图,每条边都有对应的流量限制$[l,r]$,要求每条边的流量都在规定范围内,求最大流

    设$s$是原图源点,$t$是原图汇点,$S$是新建源点,$T$是新建汇点

    先判断是否有可行流

    已经给定了源汇,咋办? 

    因为$s$流出流量=$t$流入流量

    所以$t$向$s$连一条流量为$inf$的边,就变成了无源汇上下界可行流问题

    在残量网络中,可行流的部分已经被去掉了

    那么$s$到$t$还可能有流量流过,以$s,t$为源点在残量网络中跑最大流即可

      1 #include <cmath>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define N1 210
      6 #define M1 40010
      7 #define ll long long
      8 using namespace std;
      9 const int inf=0x3f3f3f3f;
     10 
     11 int gint()
     12 {
     13     int ret=0,fh=1; char c=getchar();
     14     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     15     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     16     return ret*fh;
     17 }
     18 struct Edge{
     19 int to[M1<<1],nxt[M1<<1],flow[M1<<1],head[N1],cte;
     20 void ae(int u,int v,int f)
     21 {
     22     cte++; to[cte]=v; nxt[cte]=head[u];
     23     head[u]=cte; flow[cte]=f; //val[cte]=w;
     24 }
     25 }e;
     26 
     27 int n,m,s,t,S,T,hd,tl;
     28 int dep[N1],cur[N1],que[M1];
     29 
     30 int bfs()
     31 {
     32     int x,j,v;
     33     memset(dep,-1,sizeof(dep)); memcpy(cur,e.head,sizeof(cur));
     34     hd=1,tl=0; que[++tl]=S; dep[S]=0;
     35     while(hd<=tl)
     36     {
     37         x=que[hd++];
     38         for(j=e.head[x];j;j=e.nxt[j])
     39         {
     40             v=e.to[j]; 
     41             if( e.flow[j]>0 && dep[v]==-1 )
     42             {
     43                 dep[v]=dep[x]+1;
     44                 que[++tl]=v;
     45             }
     46         }
     47     }
     48     return dep[T]!=-1;
     49 }
     50 int dfs(int x,int limit)
     51 {
     52     if( (x==T) || (!limit) ) return limit;
     53     int j,v,flow,ans=0;
     54     for(j=cur[x];j;j=e.nxt[j])
     55     {
     56         cur[x]=j; v=e.to[j];
     57         if( (dep[v]==dep[x]+1) && ( flow=dfs(v,min(limit,e.flow[j])) ) )
     58         {
     59             e.flow[j]-=flow; limit-=flow;
     60             e.flow[j^1]+=flow; ans+=flow;
     61             if(!limit) break;
     62         }
     63     }
     64     return ans;
     65 }
     66 int Dinic()
     67 {
     68     int mxflow=0;
     69     while( bfs() )
     70         mxflow+=dfs(S,inf);
     71     return mxflow;
     72 }
     73 int ouc[N1]; 
     74 
     75 int main()
     76 {
     77     int i,j,x,y,v,l,r,ans; 
     78     scanf("%d%d%d%d",&n,&m,&s,&t); 
     79     S=0,T=n+1; e.cte=1;
     80     for(i=1;i<=m;i++) 
     81     {
     82         x=gint(), y=gint(), l=gint(), r=gint();
     83         e.ae(x,y,r-l); e.ae(y,x,0); 
     84         ouc[x]+=l; ouc[y]-=l; 
     85     }
     86     for(x=1;x<=n;x++) 
     87         if(ouc[x]<0) e.ae(S,x,-ouc[x]), e.ae(x,S,0);
     88         else e.ae(x,T,ouc[x]), e.ae(T,x,0);
     89     e.ae(t,s,inf); e.ae(s,t,0);
     90     ans=Dinic(); S=0, T=n+1;
     91     for(j=e.head[S];j;j=e.nxt[j])
     92     {
     93         v=e.to[j];
     94         if(e.flow[j]>0){ puts("please go home to sleep"); return 0; }
     95     }
     96     for(j=e.head[T];j;j=e.nxt[j])
     97     {
     98         v=e.to[j]; 
     99         if(e.flow[j^1]>0){ puts("please go home to sleep"); return 0; }
    100     }
    101     S=s, T=t;
    102     ans=Dinic();
    103     printf("%d
    ",ans);
    104     return 0;
    105 }
    View Code

    有源汇上下界最小流:

    给定一张有源汇网络流图,每条边都有对应的流量限制$[l,r]$,要求每条边的流量都在规定范围内,求最小流

    建图和有源汇上下界最大流一样

    在跑完可行流以后,先断开t->s这条边,再以t为源点,s为汇点跑最大流

    答案是可行流后t->s这条边的流量+t到s的最大流

    为什么是可行流t->s这条边的流量而不是最大流?

    可行流仅仅是可行的,不一定是最小的

    假设最小入流量$>$最小出流量的点称为入点,反之为出点

    在跑可行流时,必需的可行流是这样流的:S->入点->t->s->出点->T

    事实上,我们模拟的是这样一个过程:s->出点->入点->t

    假如有一条流量是这样的:S->入点->出点->T

    它模拟的是这样的过程:出点->入点

    这种流量对于可行流而言是多余的,它应该在第二次从t->s这条流量里被冲掉

    但由于它并不连接s,t导致它不会被干掉,所以这种情况并不能算到答案里

      1 #include <cmath>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define N1 50010
      6 #define M1 200010
      7 #define ll long long
      8 using namespace std;
      9 const ll inf=0x3f3f3f3f3f3fll;
     10 
     11 int gint()
     12 {
     13     int ret=0,fh=1; char c=getchar();
     14     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     15     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     16     return ret*fh;
     17 }
     18 struct Edge{
     19 int to[M1<<1],nxt[M1<<1],head[N1],cte; ll flow[M1<<1];
     20 void ae(int u,int v,ll f)
     21 {
     22     cte++; to[cte]=v; nxt[cte]=head[u];
     23     head[u]=cte; flow[cte]=f; //val[cte]=w;
     24 }
     25 }e;
     26 
     27 int n,m,s,t,S,T,hd,tl;
     28 int dep[N1],cur[N1],que[M1];
     29 
     30 int bfs()
     31 {
     32     int x,j,v;
     33     memset(dep,-1,sizeof(dep)); memcpy(cur,e.head,sizeof(cur));
     34     hd=1,tl=0; que[++tl]=S; dep[S]=0;
     35     while(hd<=tl)
     36     {
     37         x=que[hd++];
     38         for(j=e.head[x];j;j=e.nxt[j])
     39         {
     40             v=e.to[j]; 
     41             if( e.flow[j]>0 && dep[v]==-1 )
     42             {
     43                 dep[v]=dep[x]+1;
     44                 que[++tl]=v;
     45             }
     46         }
     47     }
     48     return dep[T]!=-1;
     49 }
     50 ll dfs(int x,ll limit)
     51 {
     52     if( (x==T) || (!limit) ) return limit;
     53     int j,v; ll flow,ans=0;
     54     for(j=cur[x];j;j=e.nxt[j])
     55     {
     56         cur[x]=j; v=e.to[j];
     57         if( (dep[v]==dep[x]+1) && ( flow=dfs(v,min(limit,e.flow[j])) ) )
     58         {
     59             e.flow[j]-=flow; limit-=flow;
     60             e.flow[j^1]+=flow; ans+=flow;
     61             if(!limit) break;
     62         }
     63     }
     64     return ans;
     65 }
     66 ll Dinic()
     67 {
     68     ll mxflow=0;
     69     while( bfs() )
     70         mxflow+=dfs(S,inf);
     71     return mxflow;
     72 }
     73 ll ouc[N1]; 
     74 
     75 int main()
     76 {
     77     int i,j,x,y,v,l,r; ll ans; 
     78     scanf("%d%d%d%d",&n,&m,&s,&t); 
     79     S=0,T=n+1; e.cte=1;
     80     for(i=1;i<=m;i++) 
     81     {
     82         x=gint(), y=gint(), l=gint(), r=gint();
     83         e.ae(x,y,r-l); e.ae(y,x,0); 
     84         ouc[x]+=l; ouc[y]-=l; 
     85     }
     86     for(x=1;x<=n;x++) 
     87         if(ouc[x]<0) e.ae(S,x,-ouc[x]), e.ae(x,S,0);
     88         else e.ae(x,T,ouc[x]), e.ae(T,x,0);
     89     e.ae(t,s,inf); e.ae(s,t,0);
     90     ans=Dinic(); S=0, T=n+1;
     91     for(j=e.head[S];j;j=e.nxt[j])
     92     {
     93         v=e.to[j];
     94         if(e.flow[j]>0){ puts("please go home to sleep"); return 0; }
     95     }
     96     for(j=e.head[T];j;j=e.nxt[j])
     97     {
     98         v=e.to[j]; 
     99         if(e.flow[j^1]>0){ puts("please go home to sleep"); return 0; }
    100     }
    101     for(j=e.head[t];j;j=e.nxt[j]) if(e.to[j]==s) 
    102         ans=e.flow[j^1], e.flow[j]=0, e.flow[j^1]=0;
    103     S=t, T=s;
    104     ans-=Dinic();
    105     printf("%lld
    ",ans);
    106     return 0;
    107 }
    View Code
  • 相关阅读:
    React在componentDidMount里面发送请求
    React 术语词汇表
    React里受控与非受控组件
    React和Vue等框架什么时候操作DOM
    【LeetCode】79. Word Search
    【LeetCode】91. Decode Ways
    【LeetCode】80. Remove Duplicates from Sorted Array II (2 solutions)
    【LeetCode】1. Two Sum
    【LeetCode】141. Linked List Cycle (2 solutions)
    【LeetCode】120. Triangle (3 solutions)
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10268891.html
Copyright © 2011-2022 走看看