/* 思路:start=0为起点,1~F中每个点为每份food的编号,F+1~F+n中为每头牛的编号,另外F+n+1~F+n+n中也为每头牛的编号,F+n+n+1~F+n+n+D中每个点为每份drink的编号,F+n+n+D+1为终点; 从start到每份food连边,权值为1,; 输入每头牛可以吃的food时,从这头牛(F+1~F+n)到能吃的food(1~F)连边,权值为1; 从当前牛(F+1~F+n)到当前牛(F+n+1~F+n+n)连边,权值为1;(每头牛只需一份食物) 输入每头牛可以喝的drink时,从这头牛(F+n+1~F+n+n)到能喝的drink(F+n+n+1~F+n+n+D)连边,权值为1; 从每份drink到终点(end=F+n+n+D+1)连边,权值为1; 最后用一般的方法求最大流即可; */ #include "stdio.h" //最大流, poj3281 #include "string.h" #include "queue" using namespace std; #define N 450 #define INF 0x3fffffff struct node { int u,v,w; int next; }edge[4*N*N]; int start,end; int n,idx; int dis[N],head[N],route[N]; int EK(); int BFS(); void init(); void adde(int u,int v,int w); void addedge(int u,int v,int w); int MIN(int x,int y) { return x<y?x:y; } int main() { int F,D; int i,j,k,a1,a2; while(scanf("%d%d%d",&n,&F,&D)!=-1) { init(); start = 0; //0->起点 end = 2*n+F+D+1; for(i=1;i<=F;i++) //1~F每个点代表每份food; adde(start,i,1); for(i=1;i<=n;i++) //F+1~F+n 每个点代表每头牛; F+n+1~F+n+n 每个点也代表每头牛; { scanf("%d%d",&a1,&a2); for(j=1;j<=a1;j++) { scanf("%d",&k); adde(k,i+F,1); //food到每头牛连边 } adde(i+F,i+F+n,1); //(牛到牛连边)每头牛只要一份食物就够了! for(j=1;j<=a2;j++) { scanf("%d",&k); adde(i+F+n,2*n+F+k,1); //牛到drink连边 } } for(i=1;i<=D;i++) adde(2*n+F+i,end,1); //drink到终点连边 int ans = EK(); //最后求最大流 printf("%d ",ans); } return 0; } void init() { idx = 0; memset(head,-1,sizeof(head)); } void adde(int u,int v,int w) { addedge(u,v,w); addedge(v,u,0); } void addedge(int u,int v,int w) { edge[idx].u = u; edge[idx].v = v; edge[idx].w = w; edge[idx].next = head[u]; head[u] = idx; idx++; } int BFS() { int i; int x,y; memset(route,-1,sizeof(route)); dis[0] = INF; route[0] = 0; queue<int> q; q.push(start); while(!q.empty()) { x = q.front(); q.pop(); for(i=head[x];i!=-1;i=edge[i].next) { y = edge[i].v; if(route[y]==-1 && edge[i].w) { route[y] = i; dis[y] = MIN(dis[x],edge[i].w); q.push(y); } } } route[0] = -1; if(route[end]==-1) return 0; return dis[end]; } int EK() { int x,y; int ans=0,kejia; while(kejia = BFS()) { ans += kejia; y = route[end]; while(y!=-1) { x = y^1; edge[y].w --; edge[x].w ++; y = route[edge[y].u]; } } return ans; }