• 【初步整理】网络流相关


    【求最大流】

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int inf=1000000000;
    const int maxn=200000;
    int Laxt[maxn],Next[maxn],To[maxn],Cap[maxn],cnt=1;
    int dis[maxn],nd[maxn],n,m;
    int add(int u,int v,int c)
    {
        Next[++cnt]=Laxt[u];
        Laxt[u]=cnt;
        To[cnt]=v;
        Cap[cnt]=c;
        
        Next[++cnt]=Laxt[v];
        Laxt[v]=cnt;
        To[cnt]=u;
        Cap[cnt]=0;
    }
    int sap(int u,int flow)
    {
        if(u==n||flow==0) return flow;
        int delta=0,tmp;
        for(int i=Laxt[u];i;i=Next[i]){
            int v=To[i];
            if(dis[v]+1==dis[u]&&Cap[i]>0){
                tmp=sap(v,min(Cap[i],flow-delta));
                delta+=tmp;
                Cap[i]-=tmp;
                Cap[i^1]+=tmp;
                if(flow==delta||dis[1]>=n) return delta;
            }
        }
        nd[dis[u]]--;
        if(nd[dis[u]]==0) dis[1]=n;
        nd[++dis[u]]++;
        return delta;
    }
    int main()
    {
        int i,j,c,ans=0,u,v;
        scanf("%d%d",&n,&m);
        for(i=1;i<=m;i++){
            scanf("%d%d%d",&u,&v,&c);
            add(u,v,c);
        }
        nd[0]=n;
        while(dis[1]<n){
            ans+=sap(1,inf);
        }
        printf("%d
    ",ans);
    }
    View Code

    【求割:】

     

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int inf=1000000000;
    const int maxn=200000;
    int Laxt[maxn],Next[maxn],To[maxn],Cap[maxn],cnt=1;
    int dis[maxn],nd[maxn],n,m;
    int S[maxn],num;
    int add(int u,int v,int c)
    {
        Next[++cnt]=Laxt[u];
        Laxt[u]=cnt;
        To[cnt]=v;
        Cap[cnt]=c;
        
        Next[++cnt]=Laxt[v];
        Laxt[v]=cnt;
        To[cnt]=u;
        Cap[cnt]=0;
    }
    void dfs(int u)
    {
        num++;
         S[u]=1;
         for(int i=Laxt[u];i;i=Next[i]){
                if(Cap[i]&&!S[To[i]])dfs(To[i]);
         }
    }
    int sap(int u,int flow)
    {
        if(u==n||flow==0) return flow;
        int delta=0,tmp;
        for(int i=Laxt[u];i;i=Next[i]){
            int v=To[i];
            if(dis[v]+1==dis[u]&&Cap[i]>0){
                tmp=sap(v,min(Cap[i],flow-delta));
                delta+=tmp;
                Cap[i]-=tmp;
                Cap[i^1]+=tmp;
                if(flow==delta||dis[1]>=n) return delta;
            }
        }
        nd[dis[u]]--;
        if(nd[dis[u]]==0) dis[1]=n;
        nd[++dis[u]]++;
        return delta;
    }
    int main()
    {
        int i,j,c,ans=0,u,v;
        scanf("%d%d",&n,&m);
        for(i=1;i<=m;i++){
            scanf("%d%d%d",&u,&v,&c);
            add(u,v,c);
        }
        nd[0]=n;
        while(dis[1]<n){
            ans+=sap(1,inf);
        }  
        dfs(1);
        printf("%d %d
    ",ans,num);
        for(i=1;i<=n;i++)
           if(S[i]) printf("%d ",i);
        return 0;
    }
    View Code

    题型整理:之前有过题目小结,但是很零散:网络流

    1,求最大流。如飞行员配对,方格取数。

    2,求割。如狼羊分割模型。

    3,费用流。

    4,二分图多重匹配。

    5,最小点覆盖,最大独立集。

    6,最小路径覆盖。

    7,最大权闭合子图。

    8,缩点。

    9,拆点。

    10,有上下界的最大流。

    11,其他:最小费用环

    慢慢整理

    HDU3549:基础模板1

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<memory.h>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int maxn=2010;
    const int inf=0x7fffffff;
    int vd[maxn],dis[maxn];
    int Laxt[maxn],Next[maxn],To[maxn],V[maxn];
    int n,m,cnt,ans;
    void _update()
    {
        memset(Laxt,0,sizeof(Laxt));
        memset(vd,0,sizeof(vd));
        memset(dis,0,sizeof(dis));
        memset(V,0,sizeof(V));
        cnt=2;
        ans=0;
    }
    void _add(int u,int v,int c)
    {
        Next[cnt]=Laxt[u];
        Laxt[u]=cnt;
        To[cnt]=v;
        V[cnt++]=c;
        Next[cnt]=Laxt[v];
        Laxt[v]=cnt;
        To[cnt]=u;
        V[cnt++]=0;
    }
    int _sap(int u,int flow)
    {
        int tmp,delta=0;
        if(flow==0||u==n) return flow;
        for(int i=Laxt[u];i;i=Next[i])
        {
            if(dis[To[i]]+1==dis[u]&&V[i]>0){
                tmp=_sap(To[i],min(flow-delta,V[i]));
                V[i]-=tmp;
                V[i^1]+=tmp;
                delta+=tmp;
                if(delta==flow||dis[1]>=n) return delta;
            }
        }
        vd[dis[u]]--;
        if(vd[dis[u]]==0) dis[1]=n+1;
        vd[++dis[u]]++;
        return delta;
    }
    int main()
    {
         int T,t,i,j,x,y,z;
         cin>>T;
         for(t=1;t<=T;t++){
             scanf("%d%d",&n,&m);
             _update();
             for(i=1;i<=m;i++){
                 scanf("%d%d%d",&x,&y,&z);
                 _add(x,y,z);
             }
             while(dis[1]<n+1){
                    ans+=_sap(1,inf);
             }
             printf("Case %d: %d
    ",t,ans);        
         }
         return 0;
    }
    View Code

    HDU1532:基础模板:2

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<memory.h>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int maxn=2010;
    const int inf=0x7fffffff;
    int vd[maxn],dis[maxn];
    int Laxt[maxn],Next[maxn],To[maxn],V[maxn];
    int n,m,cnt,ans;
    void _update()
    {
        memset(Laxt,0,sizeof(Laxt));
        memset(vd,0,sizeof(vd));
        memset(dis,0,sizeof(dis));
        memset(V,0,sizeof(V));
        cnt=2;
        ans=0;
    }
    void _add(int u,int v,int c)
    {
        Next[cnt]=Laxt[u];
        Laxt[u]=cnt;
        To[cnt]=v;
        V[cnt++]=c;
        Next[cnt]=Laxt[v];
        Laxt[v]=cnt;
        To[cnt]=u;
        V[cnt++]=0;
    }
    int _sap(int u,int flow)
    {
        int tmp,delta=0;
        if(flow==0||u==n) return flow;
        for(int i=Laxt[u];i;i=Next[i])
        {
            if(dis[To[i]]+1==dis[u]&&V[i]>0){
                tmp=_sap(To[i],min(flow-delta,V[i]));
                V[i]-=tmp;
                V[i^1]+=tmp;
                delta+=tmp;
                if(delta==flow||dis[1]>=n) return delta;
            }
        }
        vd[dis[u]]--;
        if(vd[dis[u]]==0) dis[1]=n;
        vd[++dis[u]]++;
        return delta;
    }
    int main()
    {
         int T,t,i,j,x,y,z;
          while(~scanf("%d%d",&m,&n)){
             _update();
             for(i=1;i<=m;i++){
                 scanf("%d%d%d",&x,&y,&z);
                 _add(x,y,z);
             }
             while(dis[1]<n){
                    ans+=_sap(1,inf);
             }
             printf("%d
    ",ans);        
         }
         return 0;
    }
    View Code

    HDU3605:状态压缩,好题

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<memory.h>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int maxm=401000;
    const int inf=0x7fffffff;
    int vd[maxm],dis[maxm];
    int Laxt[maxm],Next[maxm],To[maxm],V[maxm];
    int n,m,cnt,ans,s,t;
    int a[maxm],c[maxm];
    void _update()
    {
        memset(Laxt,0,sizeof(Laxt));
        memset(dis,0,sizeof(dis));
        memset(vd,0,sizeof(vd));
        memset(a,0,sizeof(a));
        memset(c,0,sizeof(c));
        cnt=2;
        ans=0;
    }
    void _add(int u,int v,int c)
    {
        Next[cnt]=Laxt[u];
        Laxt[u]=cnt;
        To[cnt]=v;
        V[cnt++]=c;
        Next[cnt]=Laxt[v];
        Laxt[v]=cnt;
        To[cnt]=u;
        V[cnt++]=0;
    }
    int _sap(int u,int flow)
    {
        int tmp,delta=0;
        if(flow==0||u==t) return flow;
        for(int i=Laxt[u];i;i=Next[i])
        {
            if(dis[To[i]]+1==dis[u]&&V[i]>0){
                tmp=_sap(To[i],min(flow-delta,V[i]));
                V[i]-=tmp;
                V[i^1]+=tmp;
                delta+=tmp;
                if(delta==flow||dis[s]>t) return delta;
            }
        }
        vd[dis[u]]--;
        if(vd[dis[u]]==0) dis[s]=t+1;
        vd[++dis[u]]++;
        return delta;
    }
    int main()
    {
        int n,m,i,j,Max,x;
        while(~scanf("%d%d",&n,&m))
        {
             _update();
             Max=0;
             for(i=1;i<=n;i++){
                int tmp=0;
                for(j=1;j<=m;j++) {
                   scanf("%d",&x);
                   tmp=tmp*2+x;
                }
                if(tmp>Max) Max=tmp;
                a[tmp]++;
             }
             s=0;t=Max+m+1;
             for(i=1;i<=m;i++) scanf("%d",&c[i]);
             for(i=1;i<=Max;i++){
                    if(a[i]>0) {
                        _add(0,i,a[i]);
                        int k=m,p=i;
                        while(k&&p){
                            int tmp=p%2;
                            p/=2;
                            if(tmp>0) _add(i,Max+k,inf);
                            k--;
                        }
                    }
             }
             for(i=1;i<=m;i++) _add(Max+i,t,c[i]);
             while(dis[s]<=t) {
                    ans+=_sap(s,inf);
             }
             if(ans==n) printf("YES
    ");
             else printf("NO
    ");
        }
        return 0;
    }
    View Code

    HDU3572:任务分配1

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<memory.h>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int maxn=510000;
    const int inf=0x7fffffff;
    int vd[maxn],dis[maxn];
    int Laxt[maxn],Next[maxn],To[maxn],V[maxn];
    int n,m,cnt,ans,s,t,num;
    void _update()
    {
        memset(Laxt,0,sizeof(Laxt));
        memset(vd,0,sizeof(vd));
        memset(dis,0,sizeof(dis));
        memset(V,0,sizeof(V));
        cnt=2;
        ans=0;
        num=0;
    }
    void _add(int u,int v,int c)
    {
        Next[cnt]=Laxt[u];
        Laxt[u]=cnt;
        To[cnt]=v;
        V[cnt++]=c;
        Next[cnt]=Laxt[v];
        Laxt[v]=cnt;
        To[cnt]=u;
        V[cnt++]=0;
    }
    int _sap(int u,int flow)
    {
        int tmp,delta=0;
        if(flow==0||u==t) return flow;
        for(int i=Laxt[u];i;i=Next[i])
        {
            if(dis[To[i]]+1==dis[u]&&V[i]>0){
                tmp=_sap(To[i],min(flow-delta,V[i]));
                V[i]-=tmp;
                V[i^1]+=tmp;
                delta+=tmp;
                if(delta==flow||dis[s]>t) return delta;
            }
        }
        vd[dis[u]]--;
        if(vd[dis[u]]==0) dis[s]=t+1;
        vd[++dis[u]]++;
        return delta;
    }
    int main()
    {
          int T,i,j,x,y,z,Case=0;
          scanf("%d",&T);
          while(T--){
             scanf("%d%d",&n,&m);
             s=0;t=500+n+1;
             _update();
             for(i=1;i<=n;i++){
                 scanf("%d%d%d",&z,&x,&y);
                 num+=z;
                 for(j=x;j<=y;j++)
                   _add(j,500+i,1);
                 _add(500+i,t,z);
             }
             for(i=1;i<=500;i++)
              _add(s,i,m);
             while(dis[s]<=t){
                    ans+=_sap(s,inf);
             }
             if(ans==num) printf("Case %d: Yes
    ",++Case);
             else printf("Case %d: No
    ",++Case);    
             printf("
    ");    
          }
          return 0;
    }
    View Code

    HDU2883:任务分配2

    HDU3081:男女配对

    HDU3046:狼羊割

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<memory.h>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int maxn=401000;
    const int inf=0x7fffffff;
    int vd[maxn],dis[maxn];
    int Laxt[maxn],Next[maxn],To[maxn],V[maxn];
    int n,m,cnt,ans,s,t;
    int num[220][220];
    int x[4]={0,1,0,-1};
    int y[4]={1,0,-1,0};
    void _update()
    {
        memset(Laxt,0,sizeof(Laxt));
        memset(vd,0,sizeof(vd));
        memset(dis,0,sizeof(dis));
        memset(V,0,sizeof(V));
        cnt=2;
        ans=0;
    }
    void _add(int u,int v,int c)
    {
        Next[cnt]=Laxt[u];
        Laxt[u]=cnt;
        To[cnt]=v;
        V[cnt++]=c;
        Next[cnt]=Laxt[v];
        Laxt[v]=cnt;
        To[cnt]=u;
        V[cnt++]=0;
    }
    int _sap(int u,int flow)
    {
        int tmp,delta=0;
        if(flow==0||u==t) return flow;
        for(int i=Laxt[u];i;i=Next[i])
        {
            if(dis[To[i]]+1==dis[u]&&V[i]>0){
                tmp=_sap(To[i],min(flow-delta,V[i]));
                V[i]-=tmp;
                V[i^1]+=tmp;
                delta+=tmp;
                if(delta==flow||dis[s]>t) return delta;
            }
        }
        vd[dis[u]]--;
        if(vd[dis[u]]==0) dis[s]=t+1;
        vd[++dis[u]]++;
        return delta;
    }
    int main()
    {
        int n,m,i,j,Case=0;
        while(~scanf("%d%d",&n,&m))
        {
             s=0;t=n*m+1;
             _update();
             for(i=1;i<=n;i++)
              for(j=1;j<=m;j++)
                scanf("%d",&num[i][j]);
             for(i=1;i<=n;i++)
              for(j=1;j<=m;j++){    
                    for(int k=0;k<4;k++)
                    if(i+x[k]>=1&&j+y[k]>=1&&i+x[k]<=n&&j+y[k]<=m){
                        if(num[i][j]==0&&num[i+x[k]][j+y[k]]==0)
                          _add((i-1)*m+j,(i+x[k]-1)*m+j+y[k],1);
                        else if(num[i][j]!=num[i+x[k]][j+y[k]])
                          _add((i-1)*m+j,(i+x[k]-1)*m+j+y[k],1);
                    }
                    if(num[i][j]==1) _add(s,(i-1)*m+j,4);
                    if(num[i][j]==2) _add((i-1)*m+j,t,4);
              }
             while(dis[s]<t+1){
                    ans+=_sap(s,inf);
             }
             printf("Case %d:
    %d
    ",++Case,ans);        
        }
        return 0;
    }
    View Code

    HDU2732:拆点

    HDU3917:最大闭合权值

    HDU3468:最大流+最短路

    HDU3861:缩点+最小路径覆盖

    #include<cstdio>
    #include<cstring>
    #include<stack>
    #include<cstdlib> 
    #include<queue>
    #include<memory.h>
    #include<algorithm>
    #include<vector>
    #include<iostream>
    using namespace std;
    const int maxn=5010;
    vector<int>G[maxn];
    vector<int>G2[maxn];
    vector<int>S;
    vector<int>Map[maxn];
    int scc[maxn],vis[maxn],n,m,scc_cnt,ans;
    int link[maxn];
    void _update(){
        for(int i=1;i<=n;i++) G[i].clear();
        for(int i=1;i<=n;i++) G2[i].clear();
        memset(link,0,sizeof(link));
        memset(vis,0,sizeof(vis));
        memset(scc,0,sizeof(scc));
        S.clear();
        ans=scc_cnt=0;
    }
    void _dfs1(int v){
        if(vis[v]) return ;
        vis[v]=1;
        int L=G[v].size();
        for(int i=0;i<L;i++)_dfs1(G[v][i]);
        S.push_back(v);
        return ;
    }
    void _dfs2(int v){
        if(scc[v]) return ;
        scc[v]=scc_cnt;
        int L=G2[v].size();
        for(int i=0;i<L;i++) _dfs2(G2[v][i]);
    }
    void _kosaraju()
    {
        for(int i=1;i<=n;i++)_dfs1(i);
        for(int i=n-1;i>=0;i--) {
            if(!scc[S[i]]) {
                scc_cnt++;
                Map[scc_cnt].clear(); 
                _dfs2(S[i]);
             }
        }
        for(int i=1;i<=n;i++)
        {
            int L=G[i].size();
            for(int j=0;j<L;j++){
                if(scc[i]!=scc[G[i][j]]){
                   Map[scc[i]].push_back(scc[G[i][j]]);
                }
            }
        }
    } 
    bool _find(int v){
        int L=Map[v].size();
        for(int i=0;i<L;i++)
        {
            if(!vis[Map[v][i]]){
                vis[Map[v][i]]=1;
                if(!link[Map[v][i]]||_find(link[Map[v][i]])){
                    link[Map[v][i]]=v;
                    return true;
                }
            }
        }
        return false;
    }
    int main()
    {
        int T,i,j,u,v;
        scanf("%d",&T);
        while(T--){
            _update();
            scanf("%d%d",&n,&m);
            for(i=1;i<=m;i++){
                scanf("%d%d",&u,&v);
                G[u].push_back(v);
                G2[v].push_back(u);
            }
            _kosaraju();
            for(i=1;i<=scc_cnt;i++){
                memset(vis,0,sizeof(vis));
                if(_find(i)) {
                  ans++;
                }
            }
            printf("%d
    ",scc_cnt-ans);//以Map图位对象,不是n 
        }
        return 0;
    }
    View Code

    HDU3488:我也不知道叫什么覆盖

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<memory.h>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int maxn=310;
    const int inf=0x7ffffff;
    int map[maxn][maxn];
    int vis1[maxn],vis2[maxn];
    int ex1[maxn],ex2[maxn];
    int lack[maxn];
    int link[maxn];
    int ans,n;
    int x1[maxn],x2[maxn],y[maxn],y2[maxn];
    int Abs(int v){
        if(v<0) v=-v;
        return v;
    }
    bool _bfs(int v)
    {
        vis1[v]=true;
        for(int i=1;i<=n;i++){
            if(!vis2[i]){
                int tmp=ex1[v]+ex2[i]-map[v][i];
                if(tmp==0){
                  vis2[i]=true;
                  if(!link[i]||_bfs(link[i])){
                     link[i]=v;
                     return true;
                  }
                }
                else if(tmp<lack[i]) lack[i]=tmp;
            }
        }
        return false;
    }
    void _KM()
    {
        int t,i,j;
        memset(link,0,sizeof(link));
        memset(ex2,0,sizeof(ex2));
        for(i=1;i<=n;i++){
            ex1[i]=map[i][1];
            for(j=2;j<=n;j++)
             if(ex1[i]<map[i][j]) ex1[i]=map[i][j];
        }
        for(t=1;t<=n;t++){
            for(i=1;i<=n;i++) lack[i]=inf;//思考:为什么在这里? 
            while(true){ 
                memset(vis1,0,sizeof(vis1));
                memset(vis2,0,sizeof(vis2));
                if(_bfs(t))  break;
                int gap=inf;
                for(i=1;i<=n;i++)
                 if(!vis2[i]&&lack[i]<gap) gap=lack[i];
                for(i=1;i<=n;i++) if(vis1[i]) ex1[i]-=gap;
                for(i=1;i<=n;i++) if(vis2[i]) ex2[i]+=gap;
                for(i=1;i<=n;i++) if(!vis2[i])lack[i]-=gap;
            }
        }
        ans=0;
        for(i=1;i<=n;i++)
           ans-=map[link[i]][i];
        ans=ans;
        printf("%d
    ",ans);
    }
    int main()
    {
        int i,j,m,T,u,v,w;
        scanf("%d",&T);
        while(T--){
          scanf("%d%d",&n,&m);
          for(i=1;i<=n;i++)
           for(j=1;j<=n;j++) map[i][j]=100000000;
           for(i=1;i<=m;i++){
                scanf("%d%d%d",&u,&v,&w);
                if(w<map[u][v]) map[u][v]=w;
           }
           for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)map[i][j]=-map[i][j];
            _KM();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    2020.11.9
    2020.11.6
    2020.11.5
    2020.11.2
    建站纪念
    退役记——CCC2020&CCO2020
    BZOJ2809&&LG1552 APIO2012派遣(线段树合并)
    BZOJ4668 冷战(LCT维护最小生成树)
    BZOJ3926&&lg3346 ZJOI诸神眷顾的幻想乡(广义后缀自动机)
    BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机)
  • 原文地址:https://www.cnblogs.com/hua-dong/p/7834447.html
Copyright © 2020-2023  润新知