有
F
F
F种食物和
D
D
D种饮料,每种食物或饮料只能供一头牛享用,且每头牛只享用一种食物和一种饮料。现在有
n
n
n头牛,每头牛都有自己喜欢的食物种类列表和饮料种类列表,问最多能使几头牛同时享用到自己喜欢的食物和饮料。
(
1
≤
f
≤
100
,
1
≤
d
≤
100
,
1
≤
n
≤
100
)
(1\leq f\leq 100,1\leq d\leq 100, 1\leq n \leq 100)
(1≤f≤100,1≤d≤100,1≤n≤100)
那么显然可以把牛拆成两个点,中间连一条流量为
1
1
1的边,这样就避免了一头牛战友多样食物,那么我们可以把食物放在左边,饮料放在右边,按照牛的喜好连边即可。
整张图的边流量全部为
1
1
1
c
o
d
e
:
code:
code:
#include <bits/stdc++.h>
int n,F,D;
int S=1,T=2;
int head[5000],tot=1;
int cur[5000];
int deep[5000];
std::queue<int>q;
struct edge{
int to;
int nxt;
int flow;
}e[5000];
void add(int x,int y,int flow){
e[++tot]={y,head[x],flow};
head[x]=tot;
e[++tot]={x,head[y],0};
head[y]=tot;
}
bool bfs(){
memset(deep,0,sizeof deep);
deep[S]=1;
q.push(S);
while(!q.empty()){
int X=q.front();
q.pop();
for(int i=head[X];i;i=e[i].nxt){
int y=e[i].to;
if(!deep[y]&&e[i].flow){
deep[y]=deep[X]+1;
q.push(y);
}
}
}
return deep[T];
}
int dfs(int x,int flow){
if(x==T||!flow)
return flow;
int Flow=0;
for(int &i=cur[x];i;i=e[i].nxt){
int y=e[i].to;
if(e[i].flow&&deep[y]==deep[x]+1){
if(int w=dfs(y,std::min(flow,e[i].flow))){
e[i].flow-=w;
e[i^1].flow+=w;
Flow+=w;
flow-=w;
if(!flow)
break;
}
}
}
return Flow;
}
void dinic(){
int maxflow=0;
while(bfs()){
memcpy(cur,head,sizeof head);
while(int w=dfs(S,0x3f3f3f3f))
maxflow+=w;
}
printf("%d\n",maxflow);
}
main(){
scanf("%d%d%d",&n,&F,&D);
for(int i=1;i<=F;++i)
add(S,2+i,1);
for(int i=1;i<=D;++i)
add(2+F+i,T,1);
for(int i=1;i<=n;++i){
add(2+F+D+i,2+F+D+n+i,1);
int L,R;
scanf("%d%d",&L,&R);
for(int j=1;j<=L;++j){
int x;
scanf("%d",&x);
add(2+x,2+F+D+i,1);
}
for(int j=1;j<=R;++j){
int x;
scanf("%d",&x);
add(2+F+D+n+i,2+F+x,1);
}
}
dinic();
return 0;
}