• P1231 教辅的组成


    每个物品被选多少次均由他们所连的边限制,但是从 (S) 出发的边和从 (T) 出发的边只能约束两种点,另外一种点拆成两个,加一条 (x o x′) 的流量为 1 的边即可

    #include<bits/stdc++.h>
    using namespace std;
    #define rg register
    inline int read(){
        rg char ch=getchar();
        rg int x=0,f=0;
        while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        return f?-x:x;
    }
    int n1,n2,n3,ans;
    int m1,m2,s,t;
    const int maxn=20020;
    int head[300010],ver[300010],nxt[300010],tot=1,flow[300010],hh[300010];
    int dis[300010];
    inline void add(int x,int y,int z){
        ver[++tot]=y;
        flow[tot]=z;
        nxt[tot]=head[x];
        head[x]=tot;
    }
    
    int bfs(){
        for(int i=s;i<=t;++i) hh[i]=head[i];
        queue<int> q;
        q.push(s);
        memset(dis,-1,sizeof dis);
        dis[s]=0;
        while(!q.empty()){
            int x=q.front();
            q.pop();
            for(int y,i=head[x];i;i=nxt[i]){
                y=ver[i];
                if(flow[i]&&dis[y]==-1){
                    dis[y]=dis[x]+1;
                    q.push(y);
                }
            }
        }
        return dis[t]==-1?false:true;
    }
    
    int dfs(int x,int f){
        if(x==t||f==0) return f;
        int used=0;
        for(int w,y,&i=hh[x];i;i=nxt[i]){
            y=ver[i];
            if(flow[i]&&dis[y]==dis[x]+1){
                w=dfs(y,min(f-used,flow[i]));
                if(w){
                    flow[i]-=w;
                    flow[i^1]+=w;
                    used+=w;
                    if(used==f) return f;
                }
            }
        }
        //if(!used) dis[x]=-1;
        return used;
    }
    
    inline void dinic(){
        while(bfs()) ans+=dfs(s,99999999);
    }
    
    int main(){
         n1=read(),n2=read(),n3=read();
         s=0;t=n1+n1+n2+n3+1;
         for(int i=1;i<=n2;++i) add(s,i,1),add(i,s,0);
         for(int i=1+n1+n1+n2;i<=n1+n1+n2+n3;++i) add(i,t,1),add(t,i,0);
         for(int i=1;i<=n1;++i) add(n2+i,n2+n1+i,1),add(n2+n1+i,n2+i,0);
         m1=read();
         for(int x,y,i=1;i<=m1;++i){
         	x=read(),y=read();
         	add(y,n2+x,1);
         	add(n2+x,y,0);
         }
         m2=read();
         for(int x,y,i=1;i<=m2;++i){
         	x=read(),y=read();
         	add(n1+n2+x,n1+n2+n1+y,1);
         	add(n1+n1+n2+y,n1+n2+x,0);
         }
         dinic();
         printf("%d",ans);
         return 0;
    }
    
  • 相关阅读:
    C
    A
    hdu 三部曲1 Popular Cows tarjan算法&&缩点&&拓扑排序
    hdu 三部曲 Going Home 最小费用最大流 EK算法
    hdu 三部曲 1Minimum Cost 最小费用最大流EK算法
    hdu 三部曲1 Is the Information Reliable? 差分约束 bellman_ford算法
    hdu 三部曲1 Intervals 差分约束问题 spfa算法
    hdu 三部曲 Crashing Robots
    hdu 三部曲2 Rebuilding Roads
    Codeforces 1277C As Simple as One and Two
  • 原文地址:https://www.cnblogs.com/XiaoVsun/p/13098505.html
Copyright © 2020-2023  润新知