传送门:Dining
题意:一些牛,一些食物,一些饮料,每头牛都有其喜欢的几种食物和几种饮料,求最多能给多少头牛即找到食物又找到饮料~也就是有多少个 牛---食物---饮料 的匹配,而且满足一一匹配,每个牛,食物,或饮料都只能使用一次。
分析:如果直接源点-食物-牛-汇点这样建图,那么可能会很多份食物通过某头牛传送过去,不能保证每头牛吃一份食物,因此拆点,把每头牛拆成牛-牛,边权为1,这样就能保证每头牛只能吃一份了。
#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <limits.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 100000000
#define inf 0x3f3f3f3f
#define eps 1e-6
#define N 500
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PII pair<int,int>
using namespace std;
inline int read()
{
char ch=getchar();
int x=,f=;
while(ch>''||ch<''){if(ch=='-')f=-;ch=getchar();}
while(ch<=''&&ch>=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,d,f,vs,vt,tot;
int pre[N],q[N],cur[N],h[N];
struct edge
{
int v,w,next;
edge(){}
edge(int v,int w,int next):v(v),w(w),next(next){}
}e[N*N];
void addedge(int u,int v,int w)
{
e[tot]=edge(v,w,pre[u]);
pre[u]=tot++;
}
void init()
{
memset(pre,-,sizeof(pre));
tot=;
}
/*******************dinic************************/
int bfs()
{
int head=,tail=;
memset(h,-,sizeof(h));
q[]=vs;h[vs]=;
while(head!=tail)
{
int u=q[head++];
for(int i=pre[u];~i;i=e[i].next)
{
int v=e[i].v,w=e[i].w;
if(w&&h[v]==-)
{
h[v]=h[u]+;
q[tail++]=v;
}
}
}
return h[vt]!=-;
}
int dfs(int u,int flow)
{
if(u==vt)return flow;
int used=;
for(int i=cur[u];~i;i=e[i].next)
{
int v=e[i].v,w=e[i].w;
if(h[v]==h[u]+)
{
w=dfs(v,min(flow-used,w));
e[i].w-=w;e[i^].w+=w;
if(e[i].w)cur[u]=i;
used+=w;
if(used==flow)return flow;
}
}
if(!used)h[u]=-;
return used;
}
int dinic()
{
int res=;
while(bfs())
{
for(int i=vs;i<=vt;i++)cur[i]=pre[i];
res+=dfs(vs,inf);
}
return res;
}
/********************dinic***********************/
void build()
{
vs=;vt=n*+f+d+;
for(int i=;i<=f;i++)addedge(vs,i,),addedge(i,vs,);
for(int i=;i<=d;i++)addedge(i+*n+f,vt,),addedge(vt,i+*n+f,);
for(int i=;i<=n;i++)addedge(f+i,f+n+i,),addedge(f+n+i,f+i,);
for(int i=;i<=n;i++)
{
int m1,m2,x;
m1=read();m2=read();
while(m1--)
{
x=read();
addedge(x,f+i,);
addedge(f+i,x,);
}
while(m2--)
{
x=read();
addedge(f+n+i,f+*n+x,);
addedge(f+*n+x,f+n+i,);
}
}
}
int main()
{
while(scanf("%d%d%d",&n,&f,&d)>)
{
init();
build();
printf("%d\n",dinic());
}
}