网络流
#include<map>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<iostream>
#include<algorithm>
const int MAXN = 55, NodeNum = (MAXN*5)<<1,INF = 2e8;
const int ni[2] = {-1,1};
int h,w,c,m,nw,nc,nm;
struct Edge{int v,cap,next;}edge[(NodeNum*MAXN)<<2] = {0},emp = {0};
int head[NodeNum], el , ind ,start , end;
bool hash[MAXN];int dep[NodeNum];
struct TwoNode{int in,out;}hh[MAXN],ww[MAXN],cc[MAXN],mm[MAXN],nnw,nnc,nnm;
void newedge(int u,int v,int cap)
{
++el; edge[el].v = v;
edge[el].cap = cap;
edge[el].next = head[u];
head[u] = el;
}
void newone(TwoNode &x,int flow)
{
x.in = ++ind,x.out = ++ind;
head[x.in] = head[x.out] = 0;
newedge(x.in,x.out,flow);
newedge(x.out,x.in,0);
}
int line[NodeNum], f, r;
bool BFS()
{
f = r = 0;
memset(dep,0,sizeof(dep));
line[r++] = start;
dep[start] = 1;
while(f!=r)
{
int now = line[f++];
for(int i = head[now]; i ; i = edge[i].next)
if(edge[i].cap)
{
int p = edge[i].v;
if(dep[p])continue;
else
{
dep[p] = dep[now]+1;
line[r++] = p;
}
}
}
if(dep[end])return true;
else return false;
}
int dfs(int a,int flow)
{
if(!flow || a == end)return flow;
int ret = 0;
for(int i = head[a]; i && flow; i = edge[i].next)
{
int p = edge[i].v;
if(dep[p] != dep[a] + 1 || !edge[i].cap)continue;
int ff = dfs(p,std::min(flow,edge[i].cap));
edge[i].cap -= ff ;
edge[i+ni[i&1]].cap += ff;
flow -= ff, ret += ff;
}
return ret;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("attackonworldtree.in","r",stdin);
freopen("attackonworldtree.out","w",stdout);
#endif
while(1)
{
int totflow = 0;
ind = el = 0;
scanf("%d%d%d%d%d%d%d",&h,&w,&c,&m,&nw,&nc,&nm);
if(h == -1)break;
for(int i = 1; i <= h; i++)newone(hh[i],1);
for(int i = 1; i <= w; i++)newone(ww[i],1);
for(int i = 1; i <= c; i++)newone(cc[i],1);
for(int i = 1; i <= m; i++)newone(mm[i],1);
newone(nnw,nw);
newone(nnc,nc);
newone(nnm,nm);
for(int i = 1; i <= w; i++)
{
int len, ph;scanf("%d",&len);
while(len--)
{
scanf("%d",&ph);
newedge(hh[ph].out,ww[i].in,1);
newedge(ww[i].in,hh[ph].out,0);
}
}
for(int i = 1; i <= c; i++)
{
int len, pw;scanf("%d",&len);
while(len--)
{
scanf("%d",&pw);
newedge(ww[pw].out,cc[i].in,1);
newedge(cc[i].in,ww[pw].out,0);
}
}
for(int i = 1; i <= m; i++)
{
int len, pc;scanf("%d",&len);
while(len--)
{
scanf("%d",&pc);
newedge(cc[pc].out,mm[i].in,1);
newedge(mm[i].in,cc[pc].out,0);
}
}
start = ++ind;
end = ++ind;
head[start] = head[end] = 0;
for(int i = 1 ;i <= h; i++)
{
newedge(start,hh[i].in,1);
newedge(hh[i].in,start,0);
}
for(int i = 1;i <= m; i++)
{
newedge(mm[i].out,end,1);
newedge(end,mm[i].out,0);
}
for(int i = 1; i <= h; i++)
{
newedge(hh[i].out,nnw.in,1);
newedge(nnw.in,hh[i].out,0);
}
for(int i = 1; i <= c; i++)
{
newedge(nnw.out,cc[i].in,1);
newedge(cc[i].in,nnw.out,0);
}
for(int i = 1; i <= w; i++)
{
newedge(ww[i].out,nnc.in,1);
newedge(nnc.in,ww[i].out,0);
}
for(int i = 1; i <= m; i++)
{
newedge(nnc.out,mm[i].in,1);
newedge(mm[i].in,nnc.out,0);
}
for(int i = 1; i <= c; i++)
{
newedge(cc[i].out,nnm.in,1);
newedge(nnm.in,cc[i].out,0);
}
newedge(nnm.out,end,c);
newedge(end,nnm.out,0);
totflow = 0;
while(1)//dinic
{
if(BFS() == false)break;
// memset(hash,false,sizeof(hash));
totflow += dfs(start,INF);
}
printf("%d\n",totflow);
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}