zoukankan      html  css  js  c++  java
  • [挖坑]网络流24题

     1.飞行员配对方案问题

    https://www.luogu.org/problem/show?pid=2756

    二分图匹配。

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define MAXN 100
    #define S 0
    #define T 201
    #define MAXL 10000
    #define INF 200000000
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    } 
    
    struct edge{
        int to,next,w;
    }e[2*MAXL+5];
    int head[T+5];
    int cnt=1,n,m,ans=0;
    int q[T+5];
    queue<int> qu;
    
    void ins(int f,int t,int w)
    {
        e[++cnt].next=head[f];
        head[f]=cnt;
        e[cnt].to=t;
        e[cnt].w=w;
    }
    
    void insw(int f,int t,int w)
    {
        ins(f,t,w);ins(t,f,0);
    }
    
    int dfs(int x,int f)
    {
        if(x==T) return f;
        int used=0;
        for(int i=head[x];i;i=e[i].next)
            if(e[i].w&&q[e[i].to]==q[x]+1)
            {
                int w=dfs(e[i].to,min(e[i].w,f-used));
                used+=w;
                e[i].w-=w;
                e[i^1].w+=w;    
                if(used==f) return f;
            }    
        return used;
    }
    
    bool bfs()
    {
        qu.push(S);q[S]=0;
        for(int i=1;i<=T;i++) q[i]=-1;
        while(!qu.empty())
        {
            int u=qu.front();qu.pop();
            for(int i=head[u];i;i=e[i].next)
            {
                int v=e[i].to;
                if(e[i].w&&q[v]==-1)
                {
                    q[v]=q[u]+1;
                    qu.push(v);    
                }    
            }    
        }
        return q[T]!=-1;
    }
    
    int main()
    {
        n=read();m=read();
        int x=read(),y=read();
        while(x!=-1)
        {
            insw(x,y,1);
            x=read();y=read();    
        }
        for(int i=1;i<=n;i++) insw(S,i,1);
        for(int i=1;i<=m;i++) insw(i+n,T,1);
        while(bfs())
            ans+=dfs(S,INF);    
        printf("%d
    ",ans);
        for(int i=head[S];i;i=e[i].next)
        {
            if(e[i].w) continue;int v=e[i].to;
            for(int j=head[v];j;j=e[j].next)
            {
                if(e[j].w||e[j].to==S) continue;
                printf("%d %d
    ",v,e[j].to);
            }    
        }
        return 0;
    }

     2.太空飞行计划问题

    貌似是叫做最大权闭合图...最小割就可以了..

    原题真的恶心,读入都不给数量的....换成了一道数据更大的类似的题目

    http://www.lydsy.com/JudgeOnline/problem.php?id=1497

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define T 60001
    #define S 0
    #define MAXN 60000
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    } 
    int cnt=1,ans=0,n,m;
    int head[MAXN+5];
    struct edge{
        int to,next,w;
    }e[5000000];
    int q[MAXN+5];
    queue<int> qu;
    
    void ins(int f,int t,int w)
    {
        e[++cnt].to=t;
        e[cnt].next=head[f];
        head[f]=cnt;
        e[cnt].w=w;
    }
    
    inline void insw(int f,int t,int w){ins(f,t,w);ins(t,f,0);}
    
    bool bfs()
    {
        q[S]=0;for(int i=1;i<=T;i++) q[i]=-1;
        qu.push(S);
        while(!qu.empty())
        {
            int u=qu.front();qu.pop();
            for(int i=head[u];i;i=e[i].next)
                if(e[i].w&&q[e[i].to]==-1)    
                {
                    q[e[i].to]=q[u]+1;
                    qu.push(e[i].to);    
                }    
        }
        return q[T]!=-1;
    }
    
    int dfs(int x,int f)
    {
        if(x==T) return f;
        int used=0;
        for(int i=head[x];i;i=e[i].next)
        {
            if(e[i].w&&q[e[i].to]==q[x]+1)
            {
                int w=dfs(e[i].to,min(f-used,e[i].w));
                used+=w;
                e[i].w-=w;
                e[i^1].w+=w;
                if(used==f) return f;    
            }
        }
        return used;
    }
    
    int main()
    {
        m=read();n=read();
        for(int i=1;i<=m;++i)
        {int c=read();insw(i+n,T,c);}
        for(int i=1;i<=n;i++)
        {
            int x=read();
            insw(i,x+n,INF);
            x=read();
            insw(i,x+n,INF);
            x=read();
            insw(S,i,x);ans+=x;
        }    
        while(bfs())
            ans-=dfs(S,INF);
        printf("%d
    ",ans);
        return 0;
    }

     3.最小线段覆盖问题

    最大匹配

    https://www.luogu.org/problem/show?pid=2764#sub

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define T 8001
    #define S 0
    #define MAXN 8000
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    } 
    int ne[MAXN+5];
    bool yes[MAXN+5];
    int cnt=1,ans=0,n,m;
    int head[MAXN+5];
    struct edge{
        int to,next,w;
    }e[4000002];
    int q[MAXN+5];
    queue<int> qu;
    
    void ins(int f,int t,int w)
    {
        e[++cnt].to=t;
        e[cnt].next=head[f];
        head[f]=cnt;
        e[cnt].w=w;
    }
    
    inline void insw(int f,int t,int w){ins(f,t,w);ins(t,f,0);}
    
    bool bfs()
    {
        q[S]=0;for(int i=1;i<=T;i++) q[i]=-1;
        qu.push(S);
        while(!qu.empty())
        {
            int u=qu.front();qu.pop();
            for(int i=head[u];i;i=e[i].next)
                if(e[i].w&&q[e[i].to]==-1)    
                {
                    q[e[i].to]=q[u]+1;
                    qu.push(e[i].to);    
                }    
        }
        return q[T]!=-1;
    }
    
    int dfs(int x,int f)
    {
        if(x==T) return f;
        int used=0;
        for(int i=head[x];i;i=e[i].next)
        {
            if(e[i].w&&q[e[i].to]==q[x]+1)
            {
                int w=dfs(e[i].to,min(f-used,e[i].w));
                used+=w;
                e[i].w-=w;
                e[i^1].w+=w;
                if(w) 
                {
                    ne[x]=e[i].to;
                    if(e[i].to>n) yes[e[i].to-n]=1;
                }
                if(used==f) return f;    
            }
        }
        return used;
    }
    
    int main()
    {
        n=read();m=read();int a,b;
        for(int i=1;i<=m;i++)
        {
            a=read();b=read();insw(a,b+n,1);    
        }
        for(int i=1;i<=n;i++) insw(S,i,1),insw(i+n,T,1);
        while(bfs())
            ans+=dfs(S,INF);
        for(int i=1;i<=n;i++)
        {
            if(yes[i]) continue;
            int t=i;
            while(t>0)
            {
                printf("%d ",t);
                t=ne[t]-n;
            }
            puts("");
        }
        printf("%d
    ",n-ans);
        return 0;
    }

    4.魔术球问题

    https://www.luogu.org/problem/show?pid=2765 

    这道题非常巧妙...想了好久不知道怎么构图就去看了一下题解,发现和第三题一模一样.....

    把两个能叠在一起的数字连边,求的就是求 使得最短路径覆盖数=输入的K 的最大数字。

    第一次交最大的点跑了950+ms  好像是卡过去的。

    后来想想,这道题并不需要撤销,于是就在bfs里面加了一句只往大的数字走(就是不考虑反边),只有350ms了......

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define S 0
    #define T 10000
    #define N 5500
    #define INF 200000000
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    int K,cnt=1,ans;
    struct edge{
        int to,next,w;
    }e[150005];
    int head[T+5];
    int to[T+5];
    queue<int> Q;
    int q[T+5];
    bool mark[T+5];
    
    void INS(int f,int t,int w)
    {
        e[++cnt].next=head[f];head[f]=cnt;
        e[cnt].to=t;e[cnt].w=w;
    }
    
    void ins(int f,int t,int w){INS(f,t,w);INS(t,f,0);}
    
    int dfs(int x,int f)
    {
        //cout<<"dfs"<<x<<" "<<f<<endl;
        if(x==T) return f;
        int used=0;
        for(int i=head[x];i;i=e[i].next)
        if(e[i].w&&q[e[i].to]==q[x]+1)
        {
            int w=dfs(e[i].to,min(f-used,e[i].w));
            if(w>0)
            {
                used+=w;
                e[i].w-=w;
                e[i^1].w+=w;
                mark[e[i].to-N]=1;
                to[x]=e[i].to-N;
            }
            if(used==f) return used;
        }
        if(used==0) q[x]=-1;
        return used;
    }
    
    bool bfs()
    {
        for(int i=1;i<=T;i++) q[i]=-1;q[0]=0;
        Q.push(S);
        while(!Q.empty())
        {
            int u=Q.front();Q.pop();
            for(int i=head[u];i;i=e[i].next)
            if(e[i].w&&q[e[i].to]==-1&&e[i].to>u)
             {q[e[i].to]=q[u]+1;Q.push(e[i].to);}
        }
        return q[T]!=-1;
    }
    
    int main()
    {
        K=read();
        int j;
        for(ans=1,j=1;;++ans,++j)
        {
            ins(S,ans,1);ins(ans+N,T,1);
            for(int i=1;i*i<2*ans;i++)
               if(i*i>ans)
                   ins(ans,i*i-ans+N,1);
            while(bfs()) j-=dfs(S,INF);
            if(j>K) break;
        }
        --ans;printf("%d
    ",ans);
        for(int i=1;i<=ans;i++)
        {
            if(mark[i]) continue;
            int t=i;
            while(t)
            {
                printf("%d ",t);
                t=to[t];
            }
            puts("");
        }
        return 0;
    }

     5.圆桌问题http://tyvj.cn/p/1325

    这道题模型非常的简单....但是没地方测啊....

    好不容易发现tyvj有这道题,交上去wa光了,发现居然没有spj????????

    假装已经a了

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define S 0
    #define T 501
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    queue<int> qu;
    int q[505];
    int n,m,ans=0,cnt=1;
    int head[505];
    int s[280];
    struct edge{
        int to,next,w;
    }e[100005];
    
    void INS(int f,int t,int w)
    {
        e[++cnt].next=head[f];head[f]=cnt;
        e[cnt].to=t;e[cnt].w=w;
    }
    inline void ins(int f,int t,int w){INS(f,t,w);INS(t,f,0);}
    
    int dfs(int x,int f)
    {
        if(x==T) return f;
        int used=0;
        for(int i=head[x];i;i=e[i].next)
        if(e[i].w&&q[e[i].to]==q[x]+1)
        {
            int w=dfs(e[i].to,min(e[i].w,f-used));
            e[i].w-=w;e[i^1].w+=w;
            used+=w;if(used==f) return used;
        }
        return used;
    }
    
    bool bfs()
    {
        memset(q,0,sizeof(q));qu.push(S);q[S]=1;
        while(!qu.empty())
        {
            int u=qu.front();qu.pop();
            for(int i=head[u];i;i=e[i].next)
                if(e[i].w&&!q[e[i].to])
                {q[e[i].to]=q[u]+1;qu.push(e[i].to);}
        }
        return q[T]!=0;
    }
    
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++){s[i]=read();ans+=s[i];}
        for(int i=n;i;i--) ins(S,i,s[i]);
        for(int i=1;i<=m;i++){int x=read();ins(i+n,T,x);}
        for(int i=1;i<=n;i++)for(int j=m;j;j--)ins(i,j+n,1);
        while(bfs()) ans-=dfs(S,INF);
        if(ans) return 0*puts("0");puts("1");
        for(int i=head[S];i;i=e[i].next)
        {
            for(int j=head[e[i].to];j;j=e[j].next)
                if(!e[j].w&&e[j].to>n) printf("%d ",e[j].to-n);
            puts("");
        }
        return 0;
    }

     6.餐巾计划问题/bzoj1211软件开发

    题解见www.cnblogs.com/FallDream/p/liu

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define S 0
    #define T 2001
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int  x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
     
    bool mark[T+5];
    int head[T+5],cnt=1,n,ff,fa,fb,a,b,p=0,ans=0;
    struct edge{
        int to,next,w,c;
    }e[12005];
     
    void ins(int f,int t,int w,int c){e[++cnt].next=head[f];head[f]=cnt;e[cnt].to=t;e[cnt].w=w;e[cnt].c=c;}
    void insw(int f,int t,int w,int c){ins(f,t,w,c);ins(t,f,0,-c);}
     
    int dfs(int x,int f)
    {
        if(x==T) return ans+=f*p,f;
        int used=0; mark[x]=1;
        for(int i=head[x];i;i=e[i].next)
        if(!e[i].c&&e[i].w&&!mark[e[i].to])
        {
            int w=dfs(e[i].to,min(f-used,e[i].w));
            e[i].w-=w;e[i^1].w+=w;used+=w;
            if(used==f)return f;
        }
        return used;
    }
     
    bool modlabel()
    {
        int minn=INF;
        for(int i=S;i<=T;i++)if(mark[i])
            for(int j=head[i];j;j=e[j].next) if(!mark[e[j].to]&&e[j].w)
                minn=min(minn,e[j].c);
        if(minn==INF)return false;
        for(int i=S;i<=T;i++)if(mark[i])
            for(int j=head[i];j;j=e[j].next) 
                e[j].c-=minn,e[j^1].c+=minn;
        p+=minn;
        return true;
    }
     
    int main()
    {
        n=read();ff=read();b=read();fb=read();a=read();fa=read();
        for(int i=1;i<=n;i++)
        {   
            insw(S,i,INF,ff);int x=read();insw(S,i+n,x,0);insw(i,T,x,0);
            if(i-a>0)insw(i+n-a,i,INF,fa);
            if(i-b>0)insw(i+n-b,i,INF,fb);
        }
        for(int i=1;i<n;i++)insw(i+n,i+n+1,INF,0);
        do do memset(mark,0,sizeof(mark)); while(dfs(S,INF));while(modlabel());
        printf("%d",ans);
        return 0;
    }

     7.最长递增子序列问题

    https://www.luogu.org/problem/show?pid=2766

    注意洛谷上的这题变成了不下降

    倒着dp,求出以它为起点的最长递增序列f[i]  

    每个点拆两个,一个进入,一个出去,他们之间连流量1的边

    然后对于f[i]=1 从S向它连流量1的边,对于f[i]=s,从它向T连流量1  对于 i<j且a[i]<=a[j]&&f[i]==f[j]+1 从i向j连流量1的边,跑一次最大流就是答案

    对于第三个问,我们把1号点和n号点之间的边、向ST连的边都改成INF就可以啦。

    代码不像是我写的但是确实是我写的.....

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define MN 2000
    #define ME 1000000
    #define S 0
    #define T 2001
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int f[MN + 5] , n , mx = 0 , s[MN + 5] , head[MN + 5] , cnt = 1 , q[MN + 5] , top = 0 , d[MN + 5] , ans = 0;
    struct edge{int to , next , w;}e[ME + 5];
    
    void ins(int f , int t , int w)
    {
        e[++cnt] = (edge){t , head[f] , w};head[f] = cnt;
        e[++cnt] = (edge){f , head[t] , 0};head[t] = cnt; 
    }
    
    bool bfs()
    {
        memset(d , 0 , sizeof(d));int i , j;
        for(d[q[i = top = 0] = S] = 1 ; i <= top ; i++)
            for(j = head[q[i]] ; j ; j = e[j].next)
                if(e[j].w && !d[e[j].to])
                     d[q[ ++ top ] = e[j].to]= d[q[i]] + 1;
        return d[T] > 0;
    }
    
    int dfs(int x , int f)
    {
        if(x == T) return f;
        int used = 0;
        for(int i = head[x] ; i ; i = e[i].next)
            if(e[i].w && d[e[i].to] == d[x] + 1)
            {
                int w = dfs(e[i].to , min(f - used , e[i].w));
                used += w;e[i].w -= w;e[i^1].w += w;
                if(used == f) return used;
            }
        return used;
    }
    
    int main()
    {
        n = read();
        for(int i = 1 ; i <= n ; i++) s[i] = read();
        for(int i = n + 1 ; i ; mx = max(mx , f[i]) , f[--i] = 1)
            for(int j = i+1 ; j <= n ; j++) 
                if(s[i] <= s[j])
                    f[i] = max(f[i] , f[j] + 1);
                    
        for(int i = 1 ; i <= n ; i++) ins(i , i + n , 1); 
        printf("%d
    " , mx);
        for(int i = 1 ; i <= n ; i++)
            for(int j = i + 1 ; j <= n ; j++)
                if(f[i] == f[j] + 1 && s[i] <= s[j])
                    ins(i + n , j , 1);
        for(int i = 1 ; i <= n ; i++)
        {
            if(f[i] == 1)
                ins(i + n , T , 1);
            if(f[i] == mx)
                ins(S , i , 1);
        }
                
        while(bfs())ans += dfs(S , INF);
        printf("%d
    " , ans);
        
        if(mx == 1) return 0 * printf("%d" , n);
        
        cnt = 1; ans = 0;
        memset(head , 0 ,sizeof(head));
        
        for(int i = 2 ; i < n ; i++) ins(i , i + n , 1); 
        ins(1 , 1 + n , INF);ins(n , n << 1 , INF);
        for(int i = 1 ; i <= n ; i++)
            for(int j = i + 1 ; j <= n ; j++)
                if(f[i] == f[j] + 1 && s[i] <= s[j])
                    ins(i + n , j , 1);
        for(int i = 1 ; i <= n ; i++)
        {
            if(f[i] == 1)
                ins(i + n , T , INF);
            if(f[i] == mx)
                ins(S , i , INF);
        }
        while(bfs())ans += dfs(S , INF);
        printf("%d
    " , ans);    
        return 0;
    }

    8.试题库问题

    https://www.luogu.org/problem/show?pid=2763 

    二分图乱匹配

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define S 0
    #define T 1021
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    int c[T+5],head[T+5],n,k,m,cnt=1,q[T+5],qx[T+5],top,s[T],d[T+5],ans=0;
    struct edge{
        int to,next,w;
    }e[50005];
    
    void ins(int f,int t,int w)
    {
        e[++cnt]=(edge){t,head[f],w};head[f]=cnt;
        e[++cnt]=(edge){f,head[t],0};head[t]=cnt;
    }
    
    bool bfs()
    {
        memset(d,0,sizeof(d));int i,j;
        for(d[q[i=top=0]=S]=1;i<=top;i++)
            for(int j=c[q[i]]=head[q[i]];j;j=e[j].next)
                if(e[j].w&&!d[e[j].to])
                    d[q[++top]=e[j].to]=d[q[i]]+1;
        return d[T];
    }
    
    int dfs(int x,int f)
    {
        if(x==T)return f;
        int used=0;
        for(int&i=c[x];i;i=e[i].next)
        if(e[i].w&&d[e[i].to]==d[x]+1)
        {
            int w=dfs(e[i].to,min(f-used,e[i].w));
            used+=w;e[i].w-=w;e[i^1].w+=w;
            if(used==f)return f;
        }
        return used;
    }
    
    int main()
    {
        k=read();n=read();
        for(int i=1;i<=k;i++)s[i]=read();
        for(int i=k;i;i--)
        {
            ans+=s[i];
            ins(S,i+n,s[i]);
        }
        for(int i=1;i<=n;i++)
        {
            m=read();ins(i,T,1);
            for(int j=1;j<=m;j++)
                ins(read()+n,i,1);
        }
        while(bfs()) ans-=dfs(S,INF);
        if(ans) return 0*puts("No Solution!");
        for(int i=head[S];i;i=e[i].next)
        {
            printf("%d: ",e[i].to-n);
            for(int j=head[e[i].to];j;j=e[j].next)
                if(!e[j].w&&e[j].to!=S)
                    printf("%d ",e[j].to);
            if(e[i].next)
            puts("");
        }
        return 0;
    }

     9.方格取数问题

    https://www.luogu.org/problem/show?pid=2774

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define S 0
    #define T 10001
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int n,m,cnt=1,q[T+5],d[T+5],head[T+5],c[T+5],ans=0,top;
    struct edge{
        int to,next,w;
    }e[200000];
    
    void ins(int f,int t,int w)
    {
        e[++cnt]=(edge){t,head[f],w};head[f]=cnt;
        e[++cnt]=(edge){f,head[t],0};head[t]=cnt;
    }
    
    int dfs(int x,int f)
    {
        if(x==T)return f;
        int used=0;
        for(int&i=c[x];i;i=e[i].next)
        if(e[i].w&&d[e[i].to]==d[x]+1)
        {
            int w=dfs(e[i].to,min(f-used,e[i].w));
            used+=w;e[i].w-=w;e[i^1].w+=w;
            if(used==f)return f;
        }
        return used;
    }
    
    bool bfs()
    {
        memset(d,0,sizeof(d));int i,j;
        for(d[q[i=top=0]=S]=1;i<=top;i++)
            for(int j=c[q[i]]=head[q[i]];j;j=e[j].next)
                if(e[j].w&&!d[e[j].to])
                    d[q[++top]=e[j].to]=d[q[i]]+1;
        return d[T]; 
    }
    
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                int x=read();ans+=x;
                if((i+j)&1)
                    ins(S,(i-1)*m+j,x);
                else 
                    ins((i-1)*m+j,T,x); 
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if((i+j)&1)
                {
                    int x=(i-1)*m+j;
                    if(i>1) ins(x,(i-2)*m+j,INF);
                    if(j>1) ins(x,x-1,INF);
                    if(i<n) ins(x,i*m+j,INF);
                    if(j<m) ins(x,x+1,INF);
                } 
        while(bfs())ans-=dfs(S,INF);
        cout<<ans;
        return 0;
    }

    最小割。

    10.航空计划问题

    https://www.oj.swust.edu.cn/problem/show/1746

    建图很好想吧..然后就是一个最大费用最大流   输出方案我都要吐血了

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<map>
    #define S 1
    #define T n<<1
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    map<string,int> mp;
    string st[105],x,y;
    int n,m,cnt=1,d[205],head[205],ans=0,top,tail,q[40005],p,from[5][205],mm=0,tot=1;
    bool mark[205];
    struct edge{
        int to,next,w,c;
    }e[200000];
    
    void ins(int f,int t,int w,int c)
    {
        e[++cnt]=(edge){t,head[f],w,c};head[f]=cnt;
        e[++cnt]=(edge){f,head[t],0,-c};head[t]=cnt;
    }
    
    bool spfa()
    {
          for(int i=S;i<=T;i++)d[i]=INF;
        top=tail=4000;q[top]=S;mark[S]=1;d[S]=0;
        while(top>=tail)
        {
            int u=q[tail++];
            for(int i=head[u];i;i=e[i].next)
            if(e[i].w&&d[u]+e[i].c<d[e[i].to])
            {
                d[e[i].to]=d[u]+e[i].c;from[tot][e[i].to]=i;
                if(!mark[e[i].to])
                {
                    if(d[e[i].to]<d[q[tail]]) q[--tail]=e[i].to;
                    else q[++top]=e[i].to; mark[e[i].to]=1;
                }        
            }    
            mark[u]=0;
        }
        return d[T]!=INF;
    }
    
    void mcf()
    {
        int minn=INF;
        for(int i=from[tot][T];i;i=from[tot][e[i^1].to])
            minn=min(minn,e[i].w);
        for(int i=from[tot][T];i;i=from[tot][e[i^1].to])
        {
            ans+=e[i].c*minn;
            e[i].w-=minn;e[i^1].w+=minn;    
        }
        tot+=minn;
    }
    
    void print(int from,int to)
    {
        mark[from]=1;
        for(int i=head[from];i;i=e[i].next)
            if(!mark[e[i].to]&&((!e[i].w&&e[i].c<=0)||(e[i].w&&e[i].c>=0)))
            {    
                print(e[i].to,to);
                if(e[i].to<=n) cout<<st[e[i].to]<<endl;
            }
    }
    
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)
            cin>>st[i],mp[st[i]]=i;
        for(int i=1;i<=m;i++)
        {
            cin>>x>>y;int a=mp[x],b=mp[y];
            if(a>b) swap(a,b); 
            ins(a+n,b,(a==1&&b==n)?2:1,-1);
        }
        ins(1,1+n,2,0);
        for(int i=2;i<n;i++)
            ins(i,i+n,1,0);
        ins(n,T,2,0);
        while(spfa()) mcf();--tot;
        if(tot!=2) return 0*puts("No Solution!");
        cout<<-ans<<endl;top=0;
        cout<<st[1]<<endl;
        print(S,T);
        cout<<st[1]<<endl;
        return 0;
    }

     11.星际转移问题

    https://www.luogu.org/problem/show?pid=2754

    把每个航空站都拆成天数个点,可以二分答案。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define S 0
    #define T 15002
    #define INF 2000000000
    #define num(x,y) (x)*n+(y)
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int r[25],s[25][50];
    int n,m,cnt=1,K,head[T+5],q[T+5],d[T+5],c[T+5],h[25],top=0;
    struct edge{
        int to,next,w;
    }e[T*120];
    
    void ins(int f,int t,int w)
    {
        e[++cnt]=(edge){t,head[f],w};head[f]=cnt;
        e[++cnt]=(edge){f,head[t],0};head[t]=cnt;
        //cout<<"INS"<<f<<" "<<t<<" "<<w<<endl;
    }
    
    int dfs(int x,int f)
    {
        if(x==T)return f;
        int used=0;
        for(int&i=c[x];i;i=e[i].next)
        if(e[i].w&&d[e[i].to]==d[x]+1)
        {
            int w=dfs(e[i].to,min(f-used,e[i].w));
            used+=w;e[i].w-=w;e[i^1].w+=w;
            if(used==f)return f;
        }
        return used;
    }
    
    bool bfs()
    {
        memset(d,0,sizeof(d));int i,j;
        for(d[q[top=i=0]=S]=1;i<=top;i++)
            for(int j=c[q[i]]=head[q[i]];j;j=e[j].next)
                if(e[j].w&&!d[e[j].to])
                    d[q[++top]=e[j].to]=d[q[i]]+1;
        //cout<<d[T]<<endl;
        return d[T]; 
    }
    
    void build(int x)
    {
        cnt=1;memset(head,0,sizeof(head));
        ins(S,n-1,K);
        for(int i=1;i<=m;i++)
            for(int j=1;j<=x;j++)
                ins(num(j-1,s[i][(j-1)%r[i]+1]),num(j,s[i][j%r[i]+1]),h[i]);
        for(int i=1;i<=x;i++)
            for(int j=1;j<=n;j++)
                ins(num(i-1,j),num(i,j),INF);
        ins(num(x,n),T,INF);
    }
    
    bool check(int x)
    {
        int ans=0;
        while(bfs()) ans+=dfs(S,INF);
        //cout<<x<<" "<<ans<<endl;
        return ans==K;
    } 
    
    int main()
    {
        n=read()+2;m=read();K=read();
        for(int i=1;i<=m;i++)
        {
            int x;h[i]=read();r[i]=read();
            for(int j=1;j<=r[i];j++)
                s[i][j]=(x=read())==-1?n:x==0?n-1:x;
        }
        int l=1,r=1000,ans=0,mid;
        while(l<=r)
        {
            mid=l+r>>1;build(mid);
            if(check(mid)) ans=mid,r=mid-1;
            else l=mid+1;
        }
        cout<<ans;
        return 0;
    }
    FallDream代表秋之国向您问好! 欢迎您来我的博客www.cnblogs.com/FallDream
  • 相关阅读:
    Git忽略规则.gitignore梳理
    makefile 系统脚本分析
    Kipmi0 占用CPU 100%
    kubectl检查组件健康状态异常处理
    Java 数组如何转成List集合
    用户控件中多控件自定义单击事件
    DevExpress启动窗体SplashScreen
    使用C#获取统计局行政区划代码
    解决mysqlclient模块安装问题
    com.aspose.words 类LoadOptions
  • 原文地址:https://www.cnblogs.com/FallDream/p/wangluoliu.html
Copyright © 2011-2022 走看看