P1231 教辅的组成

每个物品被选多少次均由他们所连的边限制,但是从 \(S\) 出发的边和从 \(T\) 出发的边只能约束两种点,另外一种点拆成两个,加一条 \(x \to 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;
}
posted @ 2020-06-12 11:40  __int256  阅读(138)  评论(0编辑  收藏  举报