原题:http://www.caioj.cn/problem.php?id=1116
题解:很明显是网络流,首先创造S,T。把牛拆开放在中间,n1连F,n2连D,F连S,D连T。然后跑一边最大流就行了。
#include<bits/stdc++.h>
#define inf (1<<31)-1
using namespace std;
const int N=22000;
struct E{int to,w,nxt;}data[N<<1];
int h[N],len=1,dep[N],st,ed,n,f,d;
queue<int> Q;
inline int rd(){
int x=0;int f=1;char s=getchar();
while(!isdigit(s)) f=(s=='-'?-1:f),s=getchar();
while(isdigit(s)) x=(x<<1)+(x<<3)+s-'0',s=getchar();
return x*f;
}
inline void ins(int x,int y,int c){
data[++len].to=y;data[len].w=c;data[len].nxt=h[x];h[x]=len;
data[++len].to=x;data[len].w=0;data[len].nxt=h[y];h[y]=len;
}
bool bfs(){
while(!Q.empty()) Q.pop();
memset(dep,0,sizeof dep);
dep[st]=1;Q.push(st);
while(!Q.empty()){
int x=Q.front();Q.pop();
for(int i=h[x];i;i=data[i].nxt){
int y=data[i].to;int w=data[i].w;
if(!dep[y] && w!=0){
dep[y]=dep[x]+1;
Q.push(y);
}
}
}
if(dep[ed]) return 1;
else return 0;
}
int dfs(int x,int lim){
if(x==ed) return lim;
for(int i=h[x];i;i=data[i].nxt){
int y=data[i].to;int w=data[i].w;
if(dep[y]==dep[x]+1 && w!=0){
int di=dfs(y,min(w,lim));
if(di>0){
data[i].w-=di;
data[i^1].w+=di;
return di;
}
}
}
return 0;
}
inline int dinic(){
int ans=0;
while(bfs()) ans+=dfs(st,inf);
return ans;
}
int main(){
// freopen("dinner.in","r",stdin);
n=rd();f=rd();d=rd(); len=1;memset(h,0,sizeof h);
//printf("%d %d %d\n",n,f,d);
st=0;ed=2*n+f+d+1;
for(int i=1;i<=n;i++) ins(i,i+n,1);
for(int i=1;i<=f;i++) ins(st,i+2*n,1);
for(int i=1,a,b;i<=n;i++){
a=rd();b=rd();
while(a--){
int y=rd()+2*n;ins(y,i,1);
}
while(b--){
int y=rd()+2*n+f;ins(i+n,y,1);
}
}
for(int i=1;i<=d;i++) ins(i+2*n+f,ed,1);
printf("%d\n",dinic());
return 0;
}