洛谷P1231 教辅的组成

https://www.luogu.org/problemnew/show/P1231
听说这题也可以用匹配来做?
网络流入门题。一份书册由一本书、一本练习册和一本答案组成,给出书与练习册以及书与答案的对应关系,求最多能组成多少份书册。
将书、题、答案的n1,n2,n3三组节点间建图,n2连源点,n3连汇点,容量设为1,跑一遍最大流。
注意如果不将书拆点,则一本书可以重复使用;将n1本书拆成两个连一条边,就能保证书中流过的流量也是1了。

#include 
#include 
#include 
using namespace std;
const int MX = 10001;
const int MXN = 1000001;
const int INF = 0x3f3f3f3f;
struct data{
    int u,v,nxt,flow;
}g[MXN];
int n1,n2,n3,m1,m2,u,v,ans;
int head[MXN],tot,s,t,level[6*MX],Q[MXN];
void addEdge(int u,int v,int val) {
    g[tot]=data{u,v,head[u],val};
    head[u]=tot++;
    g[tot]=data{v,u,head[v],0};
    head[v]=tot++;
}
bool bfs(int s,int t) {
    memset(level,0,sizeof(level));
    int l=-1,r=0;
    Q[r]=s;
    level[s]=1;
    while (lint u=Q[++l];
        if (u==t) return true;
        for (int i=head[u];i!=-1;i=g[i].nxt) {
            int v=g[i].v,flow=g[i].flow;
            if (level[v]==0&&flow!=0) {
                Q[++r]=v;
                level[v]=level[u]+1;
            }
        }
    }
    return false;
}
int dfs(int u,int maxFlow,int t) {
    if (u==t) return maxFlow;
    int res=0;
    for (int i=head[u];i!=-1&&resint v=g[i].v,flow=min(g[i].flow,maxFlow-res);
        if (level[v]==level[u]+1&&flow!=0) {
            flow=dfs(v,flow,t);
            g[i].flow-=flow;
            g[i^1].flow+=flow;
            res+=flow;
        }
    }
    if (res==0) level[u]=MXN;
    return res;
}
int main() {
    scanf("%d%d%d",&n1,&n2,&n3);
    memset(head,-1,sizeof(head));
    scanf("%d",&m1);
    while (m1--) {
        scanf("%d%d",&u,&v);
        addEdge(v,u+n2,1);
    }
    scanf("%d",&m2);
    while (m2--) {
        scanf("%d%d",&u,&v);
        addEdge(n2+n1+u,n2+n1+n1+v,1);
    }
    s=0,t=n1+n1+n2+n3+1;
    for (int i=1;i<=n1;++i)
        addEdge(i+n2,i+n2+n1,1);
    for (int i=1;i<=n2;++i)
        addEdge(s,i,1);
    for (int i=1;i<=n3;++i)
        addEdge(i+n2+n1+n1,t,1);

    while (bfs(s,t)) ans+=dfs(s,INF,t);
    printf("%d\n",ans);
    return 0;
}
//Version2
#include 
#include 
#include 
using namespace std;
const int MX = 10001;
const int MXN = 1000001;
const int INF = 0x3f3f3f3f;
struct data{
    int u,v,nxt,flow;
}g[MXN];
int n1,n2,n3,m1,m2,u,v,ans;
int head[MXN],tot,s,t,level[6*MX],Q[MXN];
void addEdge(int u,int v,int val) {
    g[tot]=data{u,v,head[u],val};
    head[u]=tot++;
    g[tot]=data{v,u,head[v],0};
    head[v]=tot++;
}
bool bfs(int s,int t) {
    memset(level,0,sizeof(level));
    int l=-1,r=0;
    Q[r]=s;
    level[s]=1;
    while (lint u=Q[++l];
        if (u==t) return true;
        for (int i=head[u];i!=-1;i=g[i].nxt) {
            int v=g[i].v,flow=g[i].flow;
            if (level[v]==0&&flow!=0) {
                Q[++r]=v;
                level[v]=level[u]+1;
            }
        }
    }
    return false;
}
int dfs(int u,int maxFlow,int t) {
    if (u==t) return maxFlow;
    int res=0;
    for (int i=head[u];i!=-1&&resint v=g[i].v,flow=min(g[i].flow,maxFlow-res);
        if (level[v]==level[u]+1&&flow!=0) {
            flow=dfs(v,flow,t);
            g[i].flow-=flow;
            g[i^1].flow+=flow;
            res+=flow;
        }
    }
    if (res==0) level[u]=MXN;
    return res;
}
void dinic() {    
    while(bfs(s,t)) 
        ans+=dfs(s,INF,t);    
    printf("%d\n",ans);
}
int main() {
    scanf("%d%d%d",&n1,&n2,&n3);
    memset(head,-1,sizeof(head));
    scanf("%d",&m1);
    while (m1--) {
        scanf("%d%d",&u,&v);
        addEdge(v,u+n1,1);
    }
    scanf("%d",&m2);
    while (m2--) {
        scanf("%d%d",&u,&v);
        addEdge(n2+n1+u,n2+n1+n1+v,1);
    }
    s=0,t=n1+n1+n2+n3+1;
    for (int i=1;i<=n1;++i)
        addEdge(i+n2,i+n2+n1,1);
    for (int i=1;i<=n2;++i)
        addEdge(s,i,1);
    for (int i=1;i<=n3;++i)
        addEdge(i+n2+n1+n1,t,1);    

    dinic();

    return 0;
}

你可能感兴趣的:(网络流)