题目背景
滚粗了的 HansBug 在收拾旧语文书,然而他发现了什么奇妙的东西。
题目描述
蒟蒻 HansBug 在一本语文书里面发现了一本答案,然而他却明明记得这书应该还包含一份练习题。然而出现在他眼前的书多得数不胜数,其中有书,有答案,有练习册。已知一个完整的书册均应该包含且仅包含一本书、一本练习册和一份答案,然而现在全都乱做了一团。许多书上面的字迹都已经模糊了,然而 HansBug 还是可以大致判断这是一本书还是练习册或答案,并且能够大致知道一本书和答案以及一本书和练习册的对应关系(即仅仅知道某书和某答案、某书和某练习册有可能相对应,除此以外的均不可能对应)。既然如此,HansBug 想知道在这样的情况下,最多可能同时组合成多少个完整的书册。
输入格式
第一行包含三个正整数 N_1N1、N_2N2、N_3N3,分别表示书的个数、练习册的个数和答案的个数。
第二行包含一个正整数 M_1M1,表示书和练习册可能的对应关系个数。
接下来 M_1M1 行每行包含两个正整数 xx、yy,表示第 xx 本书和第 yy 本练习册可能对应。(11leq≤xxleq≤N_1N1,11leq≤yyleq≤N_2N2)
第 M_{1+3}M1+3 行包含一个正整数 M_2M2,表述书和答案可能的对应关系个数。
接下来 M_2M2 行每行包含两个正整数 xx、yy,表示第 xx 本书和第 yy 本答案可能对应。(11leq≤xxleq≤N_1N1,11leq≤yyleq≤N_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); }