• P1231教辅的组成(最大流+拆点)


    题目背景

    滚粗了的 HansBug 在收拾旧语文书,然而他发现了什么奇妙的东西。

    题目描述

    蒟蒻 HansBug 在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习题。然而出现在他眼前的书多得数不胜数,其中有书,有答案,有练习册。已知一个完整的书册均应该包含且仅包含一本书、一本练习册和一份答案,然而现在全都乱做了一团。许多书上面的字迹都已经模糊了,然而 HansBug 还是可以大致判断这是一本书还是练习册或答案,并且能够大致知道一本书和答案以及一本书和练习册的对应关系(即仅仅知道某书和某答案、某书和某练习册有可能相对应,除此以外的均不可能对应)。既然如此,HansBug 想知道在这样的情况下,最多可能同时组合成多少个完整的书册。

    输入格式

    第一行包含三个正整数 N_1N1N_2N2N_3N3,分别表示书的个数、练习册的个数和答案的个数。

    第二行包含一个正整数 M_1M1,表示书和练习册可能的对应关系个数。

    接下来 M_1M1 行每行包含两个正整数 xx、yy,表示第 xx 本书和第 yy 本练习册可能对应。(11leqxxleqN_1N111leqyyleqN_2N2

    第 M_{1+3}M1+3 行包含一个正整数 M_2M2,表述书和答案可能的对应关系个数。

    接下来 M_2M2 行每行包含两个正整数 xx、yy,表示第 xx 本书和第 yy 本答案可能对应。(11leqxxleqN_1N111leqyyleqN_3N3

    输出格式

    输出包含一个正整数,表示最多可能组成完整书册的数目。

    Solution

    每本书拆成两个点,i和i+n1

    所有练习册与起点连边

    练习册与对应的书的第一个点连边

    书的第二个点与对应答案连边

    每本书的第一个点和第二个点连一条边

    所有答案与汇点连边

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+100;
    const int inf=1e9;
    int n1,n2,n3;
    int m1,m2;
    int n;
    int s,t;//源点,汇点
    //每本书拆成两个点,i和i+n1
    //所有练习册与起点连边 
    //练习册与对应的书的第一个点连边
    //书的第二个点与对应答案连边
    //每本书的第一个点和第二个点连一条边
    //所有答案与汇点连边 
    int head[maxn];
    int tot;
    struct node {
        int u,v,w,nxt;
    }edge[maxn*2];
    void addedge (int u,int v,int w) {
        edge[tot].u=u;
        edge[tot].v=v;
        edge[tot].w=w;
        edge[tot].nxt=head[u];
        head[u]=tot++;
    }
    
    //网络流部分
    int dep[maxn];
    int inq[maxn];
    int cur[maxn];
    int wjm;
    int maxflow=0;
    
    bool bfs () {
        for (int i=0;i<=n+1;i++) {
            cur[i]=head[i];
            dep[i]=inf;
            inq[i]=0;
        }
        dep[s]=0;
        queue<int> q;
        q.push(s);
        while (!q.empty()) {
            int u=q.front();
            q.pop();
            inq[u]=0;
            for (int i=head[u];i!=-1;i=edge[i].nxt) {
                int v=edge[i].v;
                if (dep[v]>dep[u]+1&&edge[i].w) {
                    dep[v]=dep[u]+1;
                    if (inq[v]==0) {
                        q.push(v);
                        inq[v]=1;
                    } 
                }
            }
        }
        if (dep[t]!=inf) return 1;
        return 0;
    }
    int dfs (int u,int flow) {
        int increase=0;
        if (u==t) {
            wjm=1;
            maxflow+=flow;
            return flow;
        }
        int used=0;
        for (int i=cur[u];i!=-1;i=edge[i].nxt) {
            cur[u]=i;
            int v=edge[i].v;
            if (edge[i].w&&dep[v]==dep[u]+1) {
                if (increase=dfs(v,min(flow-used,edge[i].w))) {
                    used+=increase;
                    edge[i].w-=increase;
                    edge[i^1].w+=increase;
                    if (used==flow) break;
                }
            }
        }
        return used;
    }
    int Dinic () {
        while (bfs()) {
            wjm=1;
            while (wjm==1) {
                wjm=0;
                dfs(s,inf);
            }
        }
        return maxflow;
    }
    
     
    
    
    
    
    int main () {
        scanf("%d%d%d",&n1,&n2,&n3);
        n=n1*2+n2+n3;
        for (int i=0;i<=n+1;i++) head[i]=-1;
        s=0;
        t=n+1;
        scanf("%d",&m1);
        for (int i=1;i<=m1;i++) {
            int x,y;
            scanf("%d%d",&x,&y);
            addedge(x,2*n1+y,0);
            addedge(2*n1+y,x,1);
        }
        scanf("%d",&m2);
        for (int i=1;i<=m2;i++) {
            int x,y;
            scanf("%d%d",&x,&y);
            addedge(x+n1,2*n1+n2+y,1);
            addedge(2*n1+n2+y,x+n1,0);
        }
        for (int i=1;i<=n2;i++) {
            addedge(s,i+n1*2,1);
            addedge(i+n1*2,s,0);
        }
        for (int i=1;i<=n1;i++) {
            addedge(i,i+n1,1);
            addedge(i+n1,i,0);
        }
        for (int i=1;i<=n3;i++) {
            addedge(n1*2+n2+i,t,1);
            addedge(t,n1*2+n2+i,0);
        }
        int ans=Dinic();
        printf("%d
    ",ans);
    } 
  • 相关阅读:
    51nod 1117 聪明的木匠:哈夫曼树
    51nod 1010 只包含因子2 3 5的数
    51nod 2636 卡车加油
    51nod 2989 组合数
    51nod 2652 阶乘0的数量 V2
    51nod 1103 N的倍数
    51nod 2489 小b和灯泡
    51nod 1003 阶乘后面0的数量
    51nod 2122 分解质因数
    javascript中的setter和getter
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/13322301.html
Copyright © 2020-2023  润新知