Problem:
Problem D:
Luigi's Tavern
Luigi's Tavern is a thriving tavern in the Kingdom of Nahaila. The owner of the tavern Luigi supports to
organize a party, because the main customers of the tavern are adventurers. Each adventurer has a job:
hero, warrior, cleric or mage.
Any party should meet the following conditions:
A party should have a hero.
The warrior and the hero in a party should get along with each other.
The cleric and the warrior in a party should get along with each other.
The mage and the cleric in a party should get along with each other.
It is recommended that a party has a warrior, a cleric, and a mage, but it is allowed that at most
N
W
,
N
C
and
N
m
parties does not have a warrior, a cleric, and a mage respectively.
A party without a cleric should have a warrior and a mage.
Now, the tavern has
H
heroes,
W
warriors,
C
clerics and
M
mages. Your job is to write a program to find the maximum number of parties they can form.
Input
The input consists of multiple datasets. Each dataset has the following format:
The first line of the input contains 7 non-negative integers
H
,
W
,
C
,
M
,
N
W
,
N
C
, and
N
M
, each of which is less than or equals to 50. The
i
-th of the following
W
lines contains the list of heroes who will be getting along with the warrior
i
. The list begins with a non-negative integer
n
i
, less than or equals to
H
. Then the rest of the line should contain ni positive integers, each of which indicates the ID of a hero getting along with the warrior
i
.
After these lists, the following
C
lines contain the lists of warriors getting along with the clerics in the same manner. The
j
-th line contains a list of warriors who will be getting along with the cleric
j
. Then the last
M
lines of the input contain the lists of clerics getting along with the mages, of course in the same
manner. The
k
-th line contains a list of clerics who will be getting along with the mage
k
.
The last dataset is followed by a line containing seven negative integers. This line is not a part of any dataset and should not be processed.
Output
For each dataset, you should output the maximum number of parties possible.
Sample Input
2 1 1 1 1 1 1
1 1
1 1
1 1
1 1 1 1 0 0 0
1 1
1 1
1 1
1 0 1 0 1 0 1
0
1 1 0 1 0 1 0
0
0
1 1 0 1 0 1 0
1 1
0
-1 -1 -1 -1 -1 -1 -1
Output for the Sample Input
2
1
1
0
1

Submitted solutions:

code_snippet: #include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

const int N = 20000;
const int inf = 100000;
int tot, id[N], nxt[N], lst[N], cap[N];
int H, W, C, M, Nw, Nc, Nm, S, cH, cW, cC, cM, T, n;
int d[N];
queue<int> Q;

void Add(int x, int y, int z) {
	id[++tot] = y; nxt[tot] = lst[x]; lst[x] = tot; cap[tot] = z;
	id[++tot] = x; nxt[tot] = lst[y]; lst[y] = tot; cap[tot] = 0;
}

bool bfs() {
	while (!Q.empty()) Q.pop();
	Q.push(S);
	memset(d, 0, sizeof(d)); d[S] = 1;
	while (!Q.empty()) {
		int x = Q.front(); Q.pop();
		for (int i = lst[x]; i; i = nxt[i]) {
			int y = id[i];
			if (cap[i] && !d[y]) {
				d[y] = d[x] + 1;
				if (y == T) return true;
				Q.push(y);
			}
		}
	}
	return false;
}

int find(int x, int flow) {
	if (x == T) return flow;
	int res = 0;
	for (int i = lst[x]; i; i = nxt[i]) {
		int y = id[i];
		if (cap[i] && d[y] == d[x] + 1) {
			int now = find(y, min(flow - res, cap[i]));
			res += now;
			cap[i] -= now, cap[i ^ 1] += now;
		}
	}
	if (!res) d[x] = -1;
	return res;
} 

int dinic() {
	int ans = 0;
	while (bfs())
		ans += find(S, inf);
	return ans; 
}

int main() {
	while (true) {
		scanf("%d%d%d%d%d%d%d", &H, &W, &C, &M, &Nw, &Nc, &Nm);
		if (H < 0) break;
		tot = 1; memset(lst, 0, sizeof(lst)); 
	
		S = cH = 1;
		cW = cH + H + 1;
		cC = cW + W + 1;
		cM = cC + C + 1;
		T = cM + M + 1;
		for (int i = 1; i <= H; i++) {
			Add(S, cH + i, 1);
			Add(cH + i, cH + i + T, 1);
			Add(cH + i + T, cW, 1);
		}
		Add(cW, cW + T, Nw);
		for (int i = 1; i <= W; i++) {
			Add(cW + i, cW + i + T, 1);
			Add(cW + i + T, cC, 1);
			int x;
			scanf("%d", &n);
			for (int j = 1; j <= n; j++) {
				scanf("%d", &x);
				Add(cH + x + T, cW + i, 1);
			}
		}
		Add(cC, cC + T, Nc);
		for (int i = 1; i <= C; i++) {
			Add(cW + T, cC + i, 1);
			Add(cC + i, cC + i + T, 1);
			Add(cC + i + T, cM, 1);
			int x;
			scanf("%d", &n);
			for (int j = 1; j <= n; j++) {
				scanf("%d", &x);
				Add(cW + x + T, cC + i, 1);
			}
		}
		Add(cM, cM + T, Nm);
		Add(cM + T, T, Nm);
		for (int i = 1; i <= M; i++) {
			Add(cC + T, cM + i, 1);
			Add(cM + i, cM + i + T, 1);
			Add(cM + i + T, T, 1);
			int x;
			scanf("%d", &n);
			for (int j = 1; j <= n; j++) {
				scanf("%d", &x);
				Add(cC + x + T, cM + i, 1);
			}
		}
		
		printf("%d\n", dinic());
	}
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3828
final_rank: 15

code_snippet: #include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

const int N = 20000;
const int inf = 100000;
int tot, id[N], nxt[N], lst[N], cap[N];
int H, W, C, M, Nw, Nc, Nm, S, cH, cW, cC, cM, T, n;
int d[N];
queue<int> Q;

void Add(int x, int y, int z) {
	id[++tot] = y; nxt[tot] = lst[x]; lst[x] = tot; cap[tot] = z;
	id[++tot] = x; nxt[tot] = lst[y]; lst[y] = tot; cap[tot] = 0;
}

bool bfs() {
	while (!Q.empty()) Q.pop();
	Q.push(S);
	memset(d, 0, sizeof(d)); d[S] = 1;
	while (!Q.empty()) {
		int x = Q.front(); Q.pop();
		for (int i = lst[x]; i; i = nxt[i]) {
			int y = id[i];
			if (cap[i] && !d[y]) {
				d[y] = d[x] + 1;
				if (y == T) return true;
				Q.push(y);
			}
		}
	}
	return false;
}

int find(int x, int flow) {
	if (x == T) return flow;
	int res = 0;
	for (int i = lst[x]; i; i = nxt[i]) {
		int y = id[i];
		if (cap[i] && d[y] == d[x] + 1) {
			int now = find(y, min(flow - res, cap[i]));
			res += now;
			cap[i] -= now, cap[i ^ 1] += now;
		}
	}
	if (!res) d[x] = -1;
	return res;
} 

int dinic() {
	int ans = 0;
	while (bfs())
		ans += find(S, inf);
	return ans; 
}

int main() {
	while (true) {
		scanf("%d%d%d%d%d%d%d", &H, &W, &C, &M, &Nw, &Nc, &Nm);
		if (H < 0) break;
		tot = 1; memset(lst, 0, sizeof(lst)); 
	
		S = cH = 1;
		cW = cH + H + 1;
		cC = cW + W + 1;
		cM = cC + C + 1;
		T = cM + M + 1;
		for (int i = 1; i <= H; i++) {
			Add(S, cH + i, 1);
			Add(cH + i, cH + i + T, 1);
			Add(cH + i + T, cW, 1);
		}
		Add(cW, cW + T, Nw);
		for (int i = 1; i <= W; i++) {
			Add(cW + i, cW + i + T, 1);
			Add(cW + i + T, cC, 1);
			int x;
			scanf("%d", &n);
			for (int j = 1; j <= n; j++) {
				scanf("%d", &x);
				Add(cH + x + T, cW + i, 1);
			}
		}
		Add(cC, cC + T, Nc);
		for (int i = 1; i <= C; i++) {
			Add(cW + T, cC + i, 1);
			Add(cC + i, cC + i + T, 1);
			Add(cC + i + T, cM, 1);
			int x;
			scanf("%d", &n);
			for (int j = 1; j <= n; j++) {
				scanf("%d", &x);
				Add(cW + x + T, cC + i, 1);
			}
		}
		Add(cM, cM + T, Nm);
		Add(cM + T, T, Nm);
		for (int i = 1; i <= M; i++) {
			Add(cC + T, cM + i, 1);
			Add(cM + i, cM + i + T, 1);
			Add(cM + i + T, T, 1);
			int x;
			scanf("%d", &n);
			for (int j = 1; j <= n; j++) {
				scanf("%d", &x);
				Add(cC + x + T, cM + i, 1);
			}
		}
		
		printf("%d\n", dinic());
	}
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3828
final_rank: 15

code_snippet: #include <iostream>
#include <vector>
using namespace std;

struct Edge {
	int to, cap, rev;
};

class MaxFlow {
	public:
	int size_ = 0;
	vector<vector<Edge>> G;
	vector<bool> used;
	
	void Initialize(int sz) {
		size_ = sz;
		G.resize(size_, vector<Edge>{});
		used.resize(size_, false);
	}
	
	void add_edge(int u, int v, int f) {
		//cout << u << " " << v << " " << f << endl;
		G[u].push_back(Edge{ v, f, (int)G[v].size() });
		G[v].push_back(Edge{ u, 0, (int)G[u].size() - 1 });
	}
	
	int dfs(int pos, int goal, int f) {
		if (pos == goal) return f;
		used[pos] = true;
		
		// Search All Edges
		for (int i = 0; i < (int)G[pos].size(); i++) {
			if (G[pos][i].cap == 0 || used[G[pos][i].to] == true) continue;
			int F = dfs(G[pos][i].to, goal, min(G[pos][i].cap, f));
			
			// Yay!
			if (F != 0) {
				G[pos][i].cap -= F;
				G[G[pos][i].to][G[pos][i].rev].cap += F;
				return F;
			}
		}
		
		// :(
		return 0;
	}
	
	int max_flow(int u, int v) {
		int Flow = 0;
		while (true) {
			for (int i = 0; i < size_; i++) used[i] = false;
			int ret = dfs(u, v, 1000000007);
			if (ret == 0) break;
			Flow += ret;
		}
		return Flow;
	}
};

int A1, FirstID_A1;
int A2, FirstID_A2, No_A2;
int A3, FirstID_A3, No_A3;
int A4, FirstID_A4, No_A4;
int FirstID_A5;

void solve() {
	FirstID_A1 = 0;
	FirstID_A2 = 2 * (A1);
	FirstID_A3 = 2 * (A1 + A2);
	FirstID_A4 = 2 * (A1 + A2 + A3);
	FirstID_A5 = 2 * (A1 + A2 + A3 + A4);
	
	// Add Edges (Part 1: Person)
	MaxFlow Z;
	Z.Initialize(FirstID_A5 + 10);
	for (int i = 0; i < A1; i++) Z.add_edge(FirstID_A1 + i, FirstID_A1 + A1 + i, 1);
	for (int i = 0; i < A2; i++) Z.add_edge(FirstID_A2 + i, FirstID_A2 + A2 + i, 1);
	for (int i = 0; i < A3; i++) Z.add_edge(FirstID_A3 + i, FirstID_A3 + A3 + i, 1);
	for (int i = 0; i < A4; i++) Z.add_edge(FirstID_A4 + i, FirstID_A4 + A4 + i, 1);
	
	// Add Edges (Part 2: Get Along With)
	for (int i = 0; i < A2; i++) {
		int num; cin >> num;
		for (int j = 0; j < num; j++) {
			int idx; cin >> idx; idx -= 1;
			Z.add_edge(FirstID_A1 + A1 + idx, FirstID_A2 + i, 1);
		}
	}
	for (int i = 0; i < A3; i++) {
		int num; cin >> num;
		for (int j = 0; j < num; j++) {
			int idx; cin >> idx; idx -= 1;
			Z.add_edge(FirstID_A2 + A2 + idx, FirstID_A3 + i, 1);
		}
	}
	for (int i = 0; i < A4; i++) {
		int num; cin >> num;
		for (int j = 0; j < num; j++) {
			int idx; cin >> idx; idx -= 1;
			Z.add_edge(FirstID_A3 + A3 + idx, FirstID_A4 + i, 1);
		}
	}
	
	// Add Edges (Part 3: Skip A2)
	for (int i = 0; i < A1; i++) Z.add_edge(FirstID_A1 + A1 + i, FirstID_A5 + 2, 1);
	for (int i = 0; i < A3; i++) Z.add_edge(FirstID_A5 + 3     , FirstID_A3 + i, 1);
	Z.add_edge(FirstID_A5 + 2, FirstID_A5 + 3, No_A2);
	
	// Add Edges (Part 4: Skip A3)
	for (int i = 0; i < A2; i++) Z.add_edge(FirstID_A2 + A2 + i, FirstID_A5 + 4, 1);
	for (int i = 0; i < A4; i++) Z.add_edge(FirstID_A5 + 5     , FirstID_A4 + i, 1);
	Z.add_edge(FirstID_A5 + 4, FirstID_A5 + 5, No_A3);
	
	// Add Edges (Part 5: Skip A4)
	for (int i = 0; i < A3; i++) Z.add_edge(FirstID_A3 + A3 + i, FirstID_A5 + 6, 1);
	Z.add_edge(FirstID_A5 + 7, FirstID_A5 + 1, 10000);
	Z.add_edge(FirstID_A5 + 6, FirstID_A5 + 7, No_A4);
	
	// Add Edges (Part 6: Start/Goal)
	for (int i = 0; i < A1; i++) Z.add_edge(FirstID_A5 + 0, i, 1);
	for (int i = 0; i < A4; i++) Z.add_edge(FirstID_A4 + A4 + i, FirstID_A5 + 1, 1);
	
	// Get Answer
	int Answer = Z.max_flow(FirstID_A5 + 0, FirstID_A5 + 1);
	cout << Answer << endl;
}

int main() {
	while (true) {
		cin >> A1 >> A2 >> A3 >> A4 >> No_A2 >> No_A3 >> No_A4;
		if (A1 == -1) break;
		solve();
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3672
final_rank: 14

code_snippet: #line 1 "a.cpp"
#include<iostream>
using namespace std;
#line 1 "/home/kotatsugame/library/graph/MF_Dinic.cpp"
//Dinic O(EV^2)
#include<algorithm>
#include<utility>
#include<vector>
#include<queue>
#include<limits>
template<typename T>
struct MF{
	struct edge{
		int to,rev;
		T cap;
	};
	vector<vector<edge> >G;
	vector<int>level,iter;
	MF(int n_=0):G(n_),level(n_),iter(n_){}
	void add_edge(int from,int to,T cap)
	{
		G[from].push_back({to,(int)G[to].size(),cap});
		G[to].push_back({from,(int)G[from].size()-1,0});
	}
	T dfs(int u,int t,T f)
	{
		if(u==t)return f;
		for(;iter[u]<G[u].size();iter[u]++)
		{
			edge&e=G[u][iter[u]];
			if(e.cap>0&&level[u]<level[e.to])
			{
				T d=dfs(e.to,t,min(f,e.cap));
				if(d>0)
				{
					e.cap-=d;
					G[e.to][e.rev].cap+=d;
					return d;
				}
			}
		}
		return 0;
	}
	T max_flow(int s,int t)
	{
		T ret=0;
		for(;;)
		{
			fill(level.begin(),level.end(),-1);
			queue<int>P;
			level[s]=0;
			P.push(s);
			while(!P.empty())
			{
				int u=P.front();P.pop();
				for(edge&e:G[u])
				{
					if(e.cap>0&&level[e.to]<0)
					{
						level[e.to]=level[u]+1;
						P.push(e.to);
					}
				}
			}
			if(level[t]<0)return ret;
			fill(iter.begin(),iter.end(),0);
			for(T f;(f=dfs(s,t,numeric_limits<T>::max()))>0;)ret+=f;
		}
	}
};
#line 4 "a.cpp"
int H,W,C,M,NW,NC,NM;
main()
{
	while(cin>>H>>W>>C>>M>>NW>>NC>>NM,H>=0)
	{
		MF<int>P(H+2*W+2*C+2*M+8);
		int start=H+2*W+2*C+2*M;
		int ws=start+1,wg=start+2;
		int cs=wg+1,cg=wg+2;
		int ms=cg+1,mg=cg+2;
		int goal=mg+1;
		P.add_edge(ws,wg,NW);
		P.add_edge(cs,cg,NC);
		P.add_edge(ms,mg,NM);
		P.add_edge(mg,goal,H);
		for(int i=0;i<H;i++)
		{
			P.add_edge(start,i,1);
			P.add_edge(i,ws,1);
		}
		for(int i=0;i<W;i++)
		{
			P.add_edge(H+i,H+W+i,1);
			P.add_edge(H+W+i,cs,1);
			int n;cin>>n;
			for(;n--;)
			{
				int h;cin>>h;
				P.add_edge(h-1,H+i,1);
			}
		}
		for(int i=0;i<C;i++)
		{
			P.add_edge(wg,H+2*W+i,1);
			P.add_edge(H+2*W+i,H+2*W+C+i,1);
			P.add_edge(H+2*W+C+i,ms,1);
			int n;cin>>n;
			for(;n--;)
			{
				int w;cin>>w;
				P.add_edge(H+W+w-1,H+2*W+i,1);
			}
		}
		for(int i=0;i<M;i++)
		{
			P.add_edge(cg,H+2*W+2*C+i,1);
			P.add_edge(H+2*W+2*C+i,H+2*W+2*C+M+i,1);
			P.add_edge(H+2*W+2*C+M+i,goal,1);
			int n;cin>>n;
			for(;n--;)
			{
				int c;cin>>c;
				P.add_edge(H+2*W+C+c-1,H+2*W+2*C+i,1);
			}
		}
		cout<<P.max_flow(start,goal)<<endl;
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3192
final_rank: 5

code_snippet: #include <iostream>
#include <vector>
#include <climits>
#include <queue>

using namespace std;

class Edge {
public:
	long long int to;
	long long int max_flow;
	long long int rev;
};

class Dinic {
	int V;
	bool directed;
public:
	vector<vector<Edge>>edge;
	vector<int>depth;
	vector<int>index;
	Dinic(int n, bool D) {
		n++;
		V = n;
		edge.resize(V);
		depth.resize(V);
		index.resize(V);
		directed = D;
		return;
	}
	void Add_Edge(int l, int r, int max_flow) {
		edge[l].push_back({ r,max_flow,(int)edge[r].size() });
		if (directed) {
			edge[r].push_back({ l,0,(int)edge[l].size() - 1 });
		}
		else {
			edge[r].push_back({ l,max_flow,(int)edge[l].size() - 1 });
		}
		return;
	}
	void Check_Depth(int s) {
		for (int i = 0; i < V; i++) {
			depth[i] = INT_MAX;
		}
		depth[s] = 0;
		queue<int>Q;
		Q.push(s);
		while (!Q.empty()) {
			int cn = Q.front();
			Q.pop();
			for (auto i : edge[cn]) {
				if (i.max_flow > 0 && depth[i.to] == INT_MAX) {
					depth[i.to] = depth[cn] + 1;
					Q.push(i.to);
				}
			}
		}
		return;
	}
	long long int max_flow(int v, int g, long long int ret) {
		if (v == g) {
			return ret;
		}
		for (int i = index[v]; i < edge[v].size(); i++) {
			if (edge[v][i].max_flow > 0 && depth[v] < depth[edge[v][i].to]) {
				long long int d = max_flow(edge[v][i].to, g, min(ret, edge[v][i].max_flow));
				if (d > 0) {
					edge[v][i].max_flow -= d;
					edge[edge[v][i].to][edge[v][i].rev].max_flow += d;
					return d;
				}
			}
		}
		return 0;
	}
	long long int Solve(int s, int g) {
		long long int ret = 0;
		while (1) {
			Check_Depth(s);
			if (depth[g] == INT_MAX) {
				return ret;
			}
			for (int i = 0; i < V; i++) {
				index[i] = 0;
			}
			long long int add = 0;
			while ((add = max_flow(s, g, INT_MAX)) > 0) {
				ret += add;
			}
		}
		return ret;
	}
};

int main() {
	int H, W, C, M, NW, NC, NM;
	cin >> H >> W >> C >> M >> NW >> NC >> NM;
	while (H != -1) {
		int st = H + W + C + M;
		int gl = st + 1;
		int WF = gl + 1;
		int WS = WF + 1;
		int CF = WS + 1;
		int CS = CF + 1;
		int MF = CS + 1;
		int MS = MF + 1;
		int dif = MS + 1;
		Dinic dn(MS+H+W+C+M, true);
		for (int i = 0; i < H + W + C + M; i++) {
			dn.Add_Edge(i, dif + i, 1);
		}
		for (int i = 0; i < H; i++) {
			dn.Add_Edge(st, i, 1);
		}
		for (int i = H + W + C; i < H + W + C + M; i++) {
			dn.Add_Edge(i+dif, gl, 1);
			dn.Add_Edge(CS, i, 1);
		}
		for (int i = 0; i < H; i++) {
			dn.Add_Edge(i+dif, WF, 1);
		}
		dn.Add_Edge(WF, WS, NW);
		for (int i = H; i < H + W; i++) {
			dn.Add_Edge(i+dif, CF, 1);
		}
		dn.Add_Edge(CF, CS, NC);
		for (int i = H + W; i < H + W + C; i++) {
			dn.Add_Edge(WS, i, 1);
			dn.Add_Edge(i+dif, MF, 1);
		}
		dn.Add_Edge(MF, MS, NM);
		dn.Add_Edge(MS, gl, NM);
		for (int i = H; i < H + W; i++) {
			int num;
			cin >> num;
			for (int j = 0; j < num; j++) {
				int N;
				cin >> N;
				N--;
				dn.Add_Edge(N+dif, i, 1);
			}
		}
		for (int i = H + W; i < H + W + C; i++) {
			int num;
			cin >> num;
			for (int j = 0; j < num; j++) {
				int N;
				cin >> N;
				N--;
				N += H;
				dn.Add_Edge(N+dif, i, 1);
			}
		}
		for (int i = H + W + C; i < H + W + C + M; i++) {
			int num;
			cin >> num;
			for (int j = 0; j < num; j++) {
				int N;
				cin >> N;
				N--;
				N += H + W;
				dn.Add_Edge(N+dif, i, 1);
			}
		}
		cout << dn.Solve(st, gl) << endl;
		cin >> H >> W >> C >> M >> NW >> NC >> NM;
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3412
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
const int INF = 1000000;
template <typename Cap>
struct ford_fulkerson{
  struct edge{
    int to, rev;
    Cap cap;
    edge(int to, int rev, int cap): to(to), rev(rev), cap(cap){
    }
  };
  int N;
  vector<vector<edge>> G;
  ford_fulkerson(int N): N(N), G(N){
  }
  void add_edge(int from, int to, Cap cap){
    int id1 = G[from].size();
    int id2 = G[to].size();
    G[from].push_back(edge(to, id2, cap));
    G[to].push_back(edge(from, id1, 0));
  }
  Cap max_flow(int s, int t){
    Cap flow = 0;
    while (1){
      vector<Cap> m(N, INF);
      vector<int> pv(N, -1);
      vector<int> pe(N, -1);
      vector<bool> used(N, false);
      queue<int> Q;
      Q.push(s);
      used[s] = true;
      while (!Q.empty()){
        int v = Q.front();
        Q.pop();
        int cnt = G[v].size();
        for (int i = 0; i < cnt; i++){
          int w = G[v][i].to;
          if (!used[w] && G[v][i].cap > 0){
            used[w] = true;
            m[w] = min(m[v], G[v][i].cap);
            pv[w] = v;
            pe[w] = i;
            Q.push(w);
          }
        }
      }
      if (!used[t]){
        break;
      }
      Cap f = m[t];
      for (int i = t; i != s; i = pv[i]){
        G[pv[i]][pe[i]].cap -= f;
        G[i][G[pv[i]][pe[i]].rev].cap += f;
      }
      flow += f;
    }
    return flow;
  }
};
int main(){
  while (1){
    int H, W, C, M, NW, NC, NM;
    cin >> H >> W >> C >> M >> NW >> NC >> NM;
    if (H < 0 && W < 0 && C < 0 && M < 0 && NW < 0 && NC < 0 && NM < 0){
      break;
    }
    int V = H + W + C * 2 + M * 2 + 7;
    ford_fulkerson<int> G(V);
    for (int i = 0; i < W; i++){
      int n;
      cin >> n;
      for (int j = 0; j < n; j++){
        int id;
        cin >> id;
        id--;
        G.add_edge(1 + id, 1 + H + i, 1);
      }
    }
    for (int i = 0; i < C; i++){
      int n;
      cin >> n;
      for (int j = 0; j < n; j++){
        int id;
        cin >> id;
        id--;
        G.add_edge(1 + H + id, 1 + H + W + i, 1);
      }
    }
    for (int i = 0; i < C; i++){
      G.add_edge(1 + H + W + i, 1 + H + W + C + i, 1);
    }
    for (int i = 0; i < M; i++){
      int n;
      cin >> n;
      for (int j = 0; j < n; j++){
        int id;
        cin >> id;
        id--;
        G.add_edge(1 + H + W + C + id, 1 + H + W + C * 2 + i, 1);
      }
    }
    for (int i = 0; i < M; i++){
      G.add_edge(1 + H + W + C * 2 + i, 1 + H + W + C * 2 + M + i, 1);
    }
    for (int i = 0; i < H; i++){
      G.add_edge(0, 1 + i, 1);
      G.add_edge(1 + i, V - 6, 1);
    }
    G.add_edge(V - 6, V - 5, NW);
    for (int i = 0; i < W; i++){
      G.add_edge(1 + H + i, V - 4, 1);
    }
    G.add_edge(V - 4, V - 3, NC);
    for (int i = 0; i < C; i++){
      G.add_edge(V - 5, 1 + H + W + i, 1);
      G.add_edge(1 + H + W + C + i, V - 2, 1);
    }
    G.add_edge(V - 2, V - 1, NM);
    for (int i = 0; i < M; i++){
      G.add_edge(V - 3, 1 + H + W + C * 2 + i, 1);
      G.add_edge(1 + H + W + C * 2 + M + i, V - 1, 1);
    }
    cout << G.max_flow(0, V - 1) << endl;
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3180
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using P = pair<int, int>;
const double eps = 1e-8;
const ll MOD = 1000000007;
const int INF = INT_MAX / 2;
const ll LINF = LLONG_MAX / 2;
template <typename T1, typename T2>
bool chmax(T1 &a, const T2 &b) {
  if(a < b) {a = b; return true;}
  return false;
}
template <typename T1, typename T2>
bool chmin(T1 &a, const T2 &b) {
  if(a > b) {a = b; return true;}
  return false;
}
template<typename T1, typename T2>
ostream& operator<<(ostream &os, const pair<T1, T2> p) {
  os << p.first << ":" << p.second;
  return os;
}
template<class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for(int i=0;i<((int)(v.size()));++i) {
    if(i) os << " ";
    os << v[i];
  }
  return os;
}
template <typename T>
struct Dinic {
  int sz;
  T inf = numeric_limits<T>::max();
  vector<int> level, iter;
  struct Edge {
    int to, rev;
    T cap;
    Edge(int to, int rev, T cap): to(to), rev(rev), cap(cap) {}
  };
  vector<vector<Edge>> g;
  Dinic(int V): sz(V) {
    g.resize(V);
    level.resize(V);
    iter.resize(V);
  };
  void add_edge(int from, int to, T cap) {
    g[from].emplace_back(to, (int)(g[to].size()), cap);
    g[to].emplace_back(from, (int)(g[from].size())-1, 0);
  }
  T max_flow(int s, int t) {
    T flow = 0;
    while(1) {
      bfs(s);
      if(level[t] < 0) return flow;
      iter.assign(sz, 0);
      T f = dfs(s, t, inf);
      while(f > 0) {
        flow += f;
        f = dfs(s, t, inf);
      }
    }
  }
private:
  void bfs(int s) {
    level.assign(sz, -1);
    level[s] = 0;
    queue<int> que;
    que.push(s);
    while(!que.empty()) {
      int now = que.front(); que.pop();
      for(auto &e: g[now]) {
        if(e.cap > 0 && level[e.to] < 0) {
          level[e.to] = level[now] + 1;
          que.push(e.to);
        }
      }
    }
  }
  T dfs(int s, int t, T flow) {
    if(s == t) return flow;
    for(int i=iter[s];i<(int)(g[s].size());++i) {
      iter[s] = i;
      auto e = g[s][i];
      if(e.cap > 0 && level[s] < level[e.to]) {
        T d = dfs(e.to, t, min(flow, e.cap));
        if(d > 0) {
          g[s][i].cap -= d;
          g[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return 0;
  }
};
int cnt = 0;
bool solve() {
  cnt++;
  int h, w, c, m, nw, nc, nm; cin >> h >> w >> c >> m >> nw >> nc >> nm;
  if(h < 0) return false;
  int k = 2*h + 2*w + 2*c + 2*m;
  Dinic<int> flow(k + 8);
  for(int i=0;i<(h);++i) {
    flow.add_edge(i+1, i+h+1, 1);
  }
  for(int i=0;i<(w);++i) {
    flow.add_edge(i+2*h+1, i+2*h+w+1, 1);
  }
  for(int i=0;i<(c);++i) {
    flow.add_edge(i+2*h+2*w+1, i+2*h+2*w+c+1, 1);
  }
  for(int i=0;i<(m);++i) {
    flow.add_edge(i+2*h+2*w+2*c+1, i+2*h+2*w+2*c+m+1, 1);
  }
  for(int i=0;i<(h);++i) {
    flow.add_edge(0, i+1, 1);
  }
  for(int i=0;i<(w);++i) {
    int t; cin >> t;
    set<int> st;
    for(int j=0;j<(t);++j) {
      int hj;
      cin >> hj;
      hj--;
      st.insert(hj);
    }
    for(auto hj: st) {
      flow.add_edge(hj+h+1, i+2*h+1, 1);
    }
  }
  for(int i=0;i<(c);++i) {
    int t; cin >> t;
    set<int> st;
    for(int j=0;j<(t);++j) {
      int cj;
      cin >> cj;
      cj--;
      st.insert(cj);
    }
    for(auto &cj: st) {
      flow.add_edge(cj+2*h+w+1, i+2*h+2*w+1, 1);
    }
  }
  for(int i=0;i<(m);++i) {
    int t; cin >> t;
    set<int> st;
    for(int j=0;j<(t);++j) {
      int mj;
      cin >> mj;
      mj--;
      st.insert(mj);
    }
    for(auto &mj: st) {
      flow.add_edge(mj+2*h+2*w+c+1, i+2*h+2*w+2*c+1, 1);
    }
  }
  for(int i=0;i<(m);++i) {
    flow.add_edge(i+2*h+2*w+2*c+m+1, k+7, 1);
  }
  flow.add_edge(k+1, k+2, nw);
  for(int i=0;i<(h);++i) {
    flow.add_edge(i+1, k+1, 1);
  }
  for(int i=0;i<(c);++i) {
    flow.add_edge(k+2, i+2*h+2*w+1, 1);
  }
  flow.add_edge(k+3, k+4, nc);
  for(int i=0;i<(w);++i) {
    flow.add_edge(i+2*h+w+1, k+3, 1);
  }
  for(int i=0;i<(m);++i) {
    flow.add_edge(k+4, i+2*h+2*w+2*c+1, 1);
  }
  flow.add_edge(k+5, k+6, nm);
  for(int i=0;i<(c);++i) {
    flow.add_edge(i+2*h+2*w+c+1, k+5, 1);
  }
  flow.add_edge(k+6, k+7, INF);
  cout << flow.max_flow(0, k+7) << endl;
  return true;
}
int main() {
  cout << fixed << setprecision(10);
  while(solve()) {}
}
accuracy: 1
time_ms: 10
memory_kb: 3248
final_rank: 7

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int inf = 1e9;

struct edge{
    int to, cap, rev;
    edge(int t, int c, int r):to(t),cap(c),rev(r){}
    edge(){}
};

void add_edge(int from, int to, int cap, vector<vector<edge>> &graph){
    graph[from].emplace_back(to, cap, graph[to].size());
    graph[to].emplace_back(from, 0, (int)graph[from].size()-1);
}

int dfs(int v, int g, int flow, vector<vector<edge>>& adj, vector<bool>& used){
    if(used[v]) return -1;
    used[v] = true;
    if(v == g) return flow;
    
    for(int i=0; i<(int)adj[v].size(); i++){
        edge& next = adj[v][i];
        if(next.cap > 0){
            int ret = dfs(next.to, g, min(flow, next.cap), adj, used);
            if(ret > 0){
                next.cap -= ret;
                adj[next.to][next.rev].cap += ret;
                return ret;
            }
        }
    }
    return -1;
}

int maxflow(int s, int g, vector<vector<edge>> &graph){
    int res = 0;
    while(1){
        vector<bool> used((graph.size()+1)*2, false);
        int ret = dfs(s, g, inf, graph, used);
        if(ret==-1) break;
        res += ret;
    }
    return res;
}

int main(){
    while(1){
        int h,w,c,m,nw,nc,nm;
        cin >> h >> w >> c >> m >> nw >> nc >> nm;
        if(h == -1) break;

        vector<vector<edge>> graph((h+w+c+m)*2 +8);
        // node使用制限
        for(int i=8; i<(int)graph.size()-1; i+=2){
            add_edge(i, i+1, 1, graph);
        }
        add_edge(2, 3, nw, graph);
        add_edge(4, 5, nc, graph);
        add_edge(6, 7, nm, graph);
        // job間相性
        for(int i=0; i<w; i++){
            int num;
            cin >> num;
            for(int j=0; j<num; j++){
                int a;
                cin >> a;
                a--;
                add_edge(8 +2*a+1, 8+2*h +2*i+0, 1, graph);
            }
        }
        for(int i=0; i<c; i++){
            int num;
            cin >> num;
            for(int j=0; j<num; j++){
                int a;
                cin >> a;
                a--;
                add_edge(8+2*h +2*a+1, 8+2*h+2*w +2*i+0, 1, graph);
            }
        }
        for(int i=0; i<m; i++){
            int num;
            cin >> num;
            for(int j=0; j<num; j++){
                int a;
                cin >> a;
                a--;
                add_edge(8+2*h+2*w +2*a+1, 8+2*h+2*w+2*c +2*i+0, 1, graph);
            }
        }
        // sg
        for(int i=0; i<h; i++){
            add_edge(0, 8 +2*i+0, 1, graph);
        }
        for(int i=0; i<m; i++){
            add_edge(8+2*h+2*w+2*c +2*i+1, 1, 1, graph);
        }
        // skip
        for(int i=0; i<h; i++){
            add_edge(8+ 2*i+1, 2, 1, graph);
        }
        for(int i=0; i<w; i++){
            add_edge(8+2*h +2*i+1, 4, 1, graph);
        }
        for(int i=0; i<c; i++){
            add_edge(3, 8+2*h+2*w +2*i+0, 1, graph);
            add_edge(8+2*h+2*w +2*i+1, 6, 1, graph);
        }
        for(int i=0; i<m; i++){
            add_edge(5, 8+2*h+2*w+2*c +2*i+0, 1, graph);
        }
        add_edge(7, 1, inf, graph);

        cout << maxflow(0, 1, graph) << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3160
final_rank: 1

code_snippet: #include <cstdio>
#include <cstdint>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
#include <tuple>
#include <queue>
#include <iostream>

using namespace std;

template <typename CapTp = int, typename CostTp = int>
struct Edge {
  int to, rev;
  CapTp cap; CostTp cost;
  bool is_rev;
  Edge(int t, bool f, int r, CapTp ca, CostTp co = 0):
    to(t), rev(r), cap(ca), cost(co), is_rev(f) {}
};

template <typename CapTp = int>
struct Dinic {
  using Graph = vector<vector<Edge<CapTp>>>;
  Graph G;
  vector<int> level, iter;
  const CapTp IA;
  vector<pair<int, int>> r_edges;
  Dinic(int N, CapTp IA_ = 1<<29): IA(IA_) {
    G.resize(N);
    level.resize(N);
    iter.resize(N);
  }
  void add_edge(int from, int to, CapTp cap) {
    G[from].emplace_back(to, false, G[to].size(), cap);
    G[to].emplace_back(from, true, G[from].size()-1, 0);
    r_edges.emplace_back(to, G[to].size()-1);
  }
  CapTp get_flowed_cap(size_t k) {
    if (r_edges.size() <= k) return -1;
    int v, i; tie(v, i) = r_edges[k];
    return G[v][i].cap;
  }
  void bfs(int s) {
    fill(level.begin(), level.end(), -1);
    queue<int> que; que.push(s);
    level[s] = 0;
    while (!que.empty()) {
      int temp = que.front(); que.pop();
      for (size_t i = 0; i < G[temp].size(); ++i) {
        auto &e = G[temp][i];
        if (e.cap > 0 && level[e.to] < 0) {
          level[e.to] = level[temp] + 1;
          que.push(e.to);
        }
      }
    }
  }

  CapTp dfs(int v, int t, CapTp f) {
    if (v == t) return f;
    for (int &i = iter[v]; i < (int)G[v].size(); ++i) {
      auto &e = G[v][i];
      if (e.cap > 0 && level[v] < level[e.to]) {
        CapTp d = dfs(e.to, t, min(f, e.cap));
        if (d > 0) {
          e.cap -= d;
          G[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return 0;
  }
  CapTp max_flow(int s, int t) {
    CapTp flow = 0, f;
    while (true) {
      bfs(s);
      if (level[t] < 0) return flow;
      fill(iter.begin(), iter.end(), 0);
      while ((f = dfs(s, t, IA)) > 0) flow += f;
    }
  }
};

void add_edge(Dinic<int> &fl, int u, int v, int c, vector< tuple<int, int, int> > &edges) {
  edges.emplace_back(u, v, c);
  fl.add_edge(u, v, c);
}

int testcase_ends() {
  const int INF = 1 << 20;
  int H, W, C, M, Nw, Nc, Nm;
  cin >> H >> W >> C >> M >> Nw >> Nc >> Nm;
  if(H < 0) return 1;

  vector< tuple<int, int, int> > edges;
  int N = H + 2*(W+1) + 2*(C+1) + 2*(M+1);
  Dinic<int> fl(N+2);
  int source = N, sink = source + 1;

  // source -- hero
  for(int i=0; i<H; i++) {
    add_edge(fl, source, i, 1, edges);

    // not use (hero -- warrior)
    add_edge(fl, i, H + W, INF, edges);
  }

  // hero -- warrior
  for(int i=0; i<W; i++) {
    int x; cin >> x;

    // friend (hero)
    for(int j=0; j<x; j++) {
      int y; cin >> y; y--;
      int u = y, v = H + i;
      add_edge(fl, u, v, INF, edges);
    }
  }

  // warrior -- warrior
  for(int i=0; i<W+1; i++) {
    int u = H + i, v = H + (W + 1) + i;
    int c = (i == W ? Nw : 1);
    add_edge(fl, u, v, c, edges);
  }

  for(int i=0; i<W; i++) {
    // not use (warrior -- cleric)
    add_edge(fl, H + (W + 1) + i, H + 2*(W + 1) + C, INF, edges);
  }

  // not use warror -- cleric
  for(int i=0; i<C; i++) {
    int u = H + (W+1) + W;
    int v = H + 2*(W+1) + i;
    add_edge(fl, u, v, INF, edges);
  }
  
  // warrior -- cleric
  for(int i=0; i<C; i++) {
    int x; cin >> x;

    // friend (warrior)
    for(int j=0; j<x; j++) {
      int y; cin >> y; y--;
      int u = H + (W + 1) + y;
      int v = H + 2*(W + 1) + i;
      add_edge(fl, u, v, INF, edges);
    }
  }

  // cleric -- cleric
  for(int i=0; i<C+1; i++) {
    int u = H + 2*(W+1) + i;
    int v = H + 2*(W+1) + (C+1) + i;
    int c = (i == C ? Nc : 1);
    add_edge(fl, u, v, c, edges);
  }

  // not use cleric -- mage
  for(int i=0; i<M; i++) {
    int u = H + 2*(W+1) + (C+1) + C;
    int v = H + 2*(W+1) + 2*(C+1) + i;
    add_edge(fl, u, v, INF, edges);
  }
  
  // cleric -- mage
  for(int i=0; i<M; i++) {
    int x; cin >> x;
    for(int j=0; j<x; j++) {
      int y; cin >> y; y--;
      int u = H + 2*(W+1) + (C+1) + y;
      int v = H + 2*(W+1) + 2*(C+1) + i;
      add_edge(fl, u, v, INF, edges);
    }
  }

  // not use (cleric -- mage)
  for(int i=0; i<C; i++) {
    add_edge(fl, H + 2*(W+1) + (C+1) + i, H + 2*(W+1) + 2*(C+1) + M, INF, edges);
  }

  // mage -- mage
  for(int i=0; i<M+1; i++) {
    int u = H + 2*(W+1) + 2*(C+1) + i;
    int v = H + 2*(W+1) + 2*(C+1) + (M+1) + i;
    int c = (i == M ? Nm : 1);
    add_edge(fl, u, v, c, edges);
  }

  // (not use) mage -- sink
  for(int i=0; i<M+1; i++) {
    int u = H + 2*(W+1) + 2*(C+1) + (M+1) + i;
    int v = sink;
    add_edge(fl, u, v, INF, edges);
  }

  cout << fl.max_flow(source, sink) << endl;
  for(int i=0; ; i++) {
    int cap = fl.get_flowed_cap(i);
    if(cap < 0) break;
    if(cap > 0) {
      int u, v, c; tie(u, v, c) = edges[i];
      // fprintf(stderr, "flowed cap %02d: %d (%d, %d, %d)\n", i, cap, u, v, c);
    }
  }
  // fprintf(stderr, "edge = %zu\n", edges.size());
  return 0;
}

int main() {
  while (!testcase_ends()) {}
}
accuracy: 1
time_ms: 10
memory_kb: 3416
final_rank: 10

code_snippet: #include <cstdio>
#include <cstdint>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
#include <tuple>
#include <queue>
#include <iostream>

using namespace std;

template <typename CapTp = int, typename CostTp = int>
struct Edge {
  int to, rev;
  CapTp cap; CostTp cost;
  bool is_rev;
  Edge(int t, bool f, int r, CapTp ca, CostTp co = 0):
    to(t), rev(r), cap(ca), cost(co), is_rev(f) {}
};

template <typename CapTp = int>
struct Dinic {
  using Graph = vector<vector<Edge<CapTp>>>;
  Graph G;
  vector<int> level, iter;
  const CapTp IA;
  vector<pair<int, int>> r_edges;
  Dinic(int N, CapTp IA_ = 1<<29): IA(IA_) {
    G.resize(N);
    level.resize(N);
    iter.resize(N);
  }
  void add_edge(int from, int to, CapTp cap) {
    G[from].emplace_back(to, false, G[to].size(), cap);
    G[to].emplace_back(from, true, G[from].size()-1, 0);
    r_edges.emplace_back(to, G[to].size()-1);
  }
  CapTp get_flowed_cap(size_t k) {
    if (r_edges.size() <= k) return -1;
    int v, i; tie(v, i) = r_edges[k];
    return G[v][i].cap;
  }
  void bfs(int s) {
    fill(level.begin(), level.end(), -1);
    queue<int> que; que.push(s);
    level[s] = 0;
    while (!que.empty()) {
      int temp = que.front(); que.pop();
      for (size_t i = 0; i < G[temp].size(); ++i) {
        auto &e = G[temp][i];
        if (e.cap > 0 && level[e.to] < 0) {
          level[e.to] = level[temp] + 1;
          que.push(e.to);
        }
      }
    }
  }

  CapTp dfs(int v, int t, CapTp f) {
    if (v == t) return f;
    for (int &i = iter[v]; i < (int)G[v].size(); ++i) {
      auto &e = G[v][i];
      if (e.cap > 0 && level[v] < level[e.to]) {
        CapTp d = dfs(e.to, t, min(f, e.cap));
        if (d > 0) {
          e.cap -= d;
          G[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return 0;
  }
  CapTp max_flow(int s, int t) {
    CapTp flow = 0, f;
    while (true) {
      bfs(s);
      if (level[t] < 0) return flow;
      fill(iter.begin(), iter.end(), 0);
      while ((f = dfs(s, t, IA)) > 0) flow += f;
    }
  }
};

void add_edge(Dinic<int> &fl, int u, int v, int c, vector< tuple<int, int, int> > &edges) {
  edges.emplace_back(u, v, c);
  fl.add_edge(u, v, c);
}

int testcase_ends() {
  const int INF = 1 << 20;
  int H, W, C, M, Nw, Nc, Nm;
  cin >> H >> W >> C >> M >> Nw >> Nc >> Nm;
  if(H < 0) return 1;

  vector< tuple<int, int, int> > edges;
  int N = H + 2*(W+1) + 2*(C+1) + 2*(M+1);
  Dinic<int> fl(N+2);
  int source = N, sink = source + 1;

  // source -- hero
  for(int i=0; i<H; i++) {
    add_edge(fl, source, i, 1, edges);

    // not use (hero -- warrior)
    add_edge(fl, i, H + W, INF, edges);
  }

  // hero -- warrior
  for(int i=0; i<W; i++) {
    int x; cin >> x;

    // friend (hero)
    for(int j=0; j<x; j++) {
      int y; cin >> y; y--;
      int u = y, v = H + i;
      add_edge(fl, u, v, INF, edges);
    }
  }

  // warrior -- warrior
  for(int i=0; i<W+1; i++) {
    int u = H + i, v = H + (W + 1) + i;
    int c = (i == W ? Nw : 1);
    add_edge(fl, u, v, c, edges);
  }

  for(int i=0; i<W; i++) {
    // not use (warrior -- cleric)
    add_edge(fl, H + (W + 1) + i, H + 2*(W + 1) + C, INF, edges);
  }

  // not use warror -- cleric
  for(int i=0; i<C; i++) {
    int u = H + (W+1) + W;
    int v = H + 2*(W+1) + i;
    add_edge(fl, u, v, INF, edges);
  }
  
  // warrior -- cleric
  for(int i=0; i<C; i++) {
    int x; cin >> x;

    // friend (warrior)
    for(int j=0; j<x; j++) {
      int y; cin >> y; y--;
      int u = H + (W + 1) + y;
      int v = H + 2*(W + 1) + i;
      add_edge(fl, u, v, INF, edges);
    }
  }

  // cleric -- cleric
  for(int i=0; i<C+1; i++) {
    int u = H + 2*(W+1) + i;
    int v = H + 2*(W+1) + (C+1) + i;
    int c = (i == C ? Nc : 1);
    add_edge(fl, u, v, c, edges);
  }

  // not use cleric -- mage
  for(int i=0; i<M; i++) {
    int u = H + 2*(W+1) + (C+1) + C;
    int v = H + 2*(W+1) + 2*(C+1) + i;
    add_edge(fl, u, v, INF, edges);
  }
  
  // cleric -- mage
  for(int i=0; i<M; i++) {
    int x; cin >> x;
    for(int j=0; j<x; j++) {
      int y; cin >> y; y--;
      int u = H + 2*(W+1) + (C+1) + y;
      int v = H + 2*(W+1) + 2*(C+1) + i;
      add_edge(fl, u, v, INF, edges);
    }
  }

  // not use (cleric -- mage)
  for(int i=0; i<C; i++) {
    add_edge(fl, H + 2*(W+1) + (C+1) + i, H + 2*(W+1) + 2*(C+1) + M, INF, edges);
  }

  // mage -- mage
  for(int i=0; i<M+1; i++) {
    int u = H + 2*(W+1) + 2*(C+1) + i;
    int v = H + 2*(W+1) + 2*(C+1) + (M+1) + i;
    int c = (i == M ? Nm : 1);
    add_edge(fl, u, v, c, edges);
  }

  // (not use) mage -- sink
  for(int i=0; i<M+1; i++) {
    int u = H + 2*(W+1) + 2*(C+1) + (M+1) + i;
    int v = sink;
    add_edge(fl, u, v, INF, edges);
  }

  cout << fl.max_flow(source, sink) << endl;
  for(int i=0; ; i++) {
    int cap = fl.get_flowed_cap(i);
    if(cap < 0) break;
    if(cap > 0) {
      int u, v, c; tie(u, v, c) = edges[i];
      // fprintf(stderr, "flowed cap %02d: %d (%d, %d, %d)\n", i, cap, u, v, c);
    }
  }
  // fprintf(stderr, "edge = %zu\n", edges.size());
  return 0;
}

int main() {
  while (!testcase_ends()) {}
}
accuracy: 1
time_ms: 10
memory_kb: 3376
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using i64=int_fast64_t;
using pii=pair<int,int>;
template <class T> constexpr T inf=numeric_limits<T>::max() / (T)2;
template <class T> using minheap=priority_queue<T,vector<T>,greater<T>>;
#define fir first
#define sec second
#define mkp make_pair
#define mkt make_tuple
#define emb emplace_back
#define all(v) begin(v),end(v)




struct edge {
    int to;
    int cap;
    int rev;
    edge(int a,int b,int c) : to(a),cap(b),rev(c) {}
};

bool vis[668];
vector<edge> grh[668];

void addedge(int s,int t,int cp) {
    int ss=grh[s].size();
    int tt=grh[t].size();
    grh[s].emb(t,cp,tt);
    grh[t].emb(s,0,ss);
}

bool dfs(int x,int t) {
    vis[x]=true;
    if(x==t) return true; 
    int i=-1;
    for(auto &e:grh[x]) {
        ++i;
        if(vis[e.to] || e.cap<=0) continue;
        if(dfs(e.to,t)) {
            e.cap--;
            grh[e.to][e.rev].cap++;
            return true;
        }
    }
    return false;
}

int maxflow(int s,int t) {
    int ret=0;
    while(memset(vis,0,sizeof(vis)), dfs(s,t)) {
        ret++;
    }
    return ret;
}

int H,W,C,M,nw,nc,nm;

void solve() {
    memset(grh,0,sizeof(grh));

    const int s=300;
    const int t=301;
    const int wnone1=302,wnone2=303,cnone1=304,cnone2=305,mnone=306;

    addedge(wnone1,wnone2,nw);
    addedge(cnone1,cnone2,nc);
    addedge(mnone,t,nm);

    for(int i=0; i<H; ++i) {
        addedge(s,i,1);
        addedge(i,wnone1,1);
    }

    for(int i=0,k; i<W; ++i) {
        cin>>k;
        for(int j=0,h; j<k; ++j) {
            cin>>h;
            h--;
            addedge(h,i+H,1);
        }
        addedge(i+H,i+H+334,1);
        addedge(i+H+334,cnone1,1);
    }

    for(int i=0,k; i<C; ++i) {
        cin>>k;
        for(int j=0,w; j<k; ++j) {
            cin>>w;
            w--;
            addedge(w+H+334,i+H+W,1);
        }
        addedge(wnone2,H+W+i,1);
        addedge(i+W+H,i+H+W+334,1);
        addedge(H+W+i+334,mnone,1);
    }

    for(int i=0,k; i<M; ++i) {
        cin>>k;
        for(int j=0,c; j<k; ++j) {
            cin>>c;
            c--;
            addedge(c+H+W+334,i+H+W+C,1);
        }
        addedge(cnone2,i+H+W+C,1);
        addedge(i+H+W+C,i+H+W+C+334,1);
        addedge(i+H+W+C+334,t,1);
    }
    
    cout<<maxflow(s,t)<<endl;
}


signed main() {
    #ifdef LOCAL
        freopen("stdin.txt","rt",stdin);
    #endif

    while(cin>>H>>W>>C>>M>>nw>>nc>>nm) {
        if(max({H,W,C,M,nw,nc,nm})<0) break;
        solve();
    }
}
accuracy: 1
time_ms: 10
memory_kb: 5104
final_rank: 19

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Weight=long long;

struct Edge{
    int to;
    Weight cap,rev;
    Weight cost;
};

using Edges=vector<Edge>;
using Graph=vector<Edges>;

class Flow{
    const Weight INF=1e9+7;
    const bool isNegative=false;
    int N;
    Graph g;
    vector<int> level;
    vector<int> iter;
    void bfs(int s);
    Weight dfs(int v,int t,Weight f);
    public:
    Flow(int N):N(N),g(N){};
    void addEdge(int from,int to,Weight cap);
    void addEdge(int from,int to,Weight cap,Weight cost);
    Weight maxFlow(int s,int t);
    Weight minCostFlow(int s,int t,Weight f);
};


void Flow::addEdge(int from,int to,Weight cap){
    g[from].push_back({to,cap,int(g[to].size()),0});
    g[to].push_back({from,Weight(0),int(g[from].size())-1,0});
}

void Flow::addEdge(int from,int to,Weight cap,Weight cost){
    g[from].push_back({to,cap,int(g[to].size()),cost});
    g[to].push_back({from,Weight(0),int(g[from].size())-1,-cost});
}
Weight Flow::maxFlow(int s,int t){
    Weight flow=0;
    while(true){
        bfs(s);
        if(level[t]<0) return flow;
        iter.assign(N,0);
        Weight f;
        while((f=dfs(s,t,INF))>0){
            flow+=f;
        }
    }
}
void Flow::bfs(int s){
    level.assign(N,-1);
    queue<int> que;
    level[s]=0;
    que.push(s);
    while(!que.empty()){
        int v=que.front(); que.pop();
        for(int i=0;i<g[v].size();i++){
            Edge &e=g[v][i];
            if(e.cap>0 && level[e.to]<0){
                level[e.to]=level[v]+1;
                que.push(e.to);
            }
        }
    }
}

Weight Flow::dfs(int v,int t,Weight f){
    if(v==t) return f;
    for(int& i=iter[v];i<g[v].size();i++){
        Edge& e=g[v][i];
        if(e.cap>0 && level[v]<level[e.to]){
            Weight d=dfs(e.to,t,min(f,e.cap));
            if(d>0){
                e.cap-=d;
                g[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}

Weight Flow::minCostFlow(int s,int t,Weight f){
    using P=pair<Weight,int>;
    Weight res=0;
    vector<Weight> h(N,0);
    vector<int> used(N),preve(N),prevv(N);
    vector<Weight> dist(N);
    while(f>0){    
        fill(dist.begin(),dist.end(),INF);
        dist[s]=0;
        if(!isNegative){
            //Dijkstra
            fill(used.begin(),used.end(),0);
            priority_queue<P,vector<P>,greater<P>> que;
            que.push(make_pair(Weight(0),s));
            while(!que.empty()){
                P p=que.top(); que.pop();
                int v=p.second;
                if(used[v]) continue;
                used[v]=true;
                for(int i=0;i<g[v].size();i++){
                    Edge &e=g[v][i];
                    if(e.cap>0 && dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){
                        dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
                        prevv[e.to]=v;
                        preve[e.to]=i;
                        que.push(make_pair(dist[e.to],e.to));
                    }
                }
            }
        }else{
            //Bermanford
            bool update=true;
            while(update){
                update=false;
                for(int v=0;v<N;v++){
                    if(dist[v]==INF) continue;
                    for(int i=0;i<g[v].size();i++){
                        Edge &e=g[v][i];
                        if(e.cap>0 && dist[e.to]>dist[v]+e.cost){
                            dist[e.to]=dist[v]+e.cost;
                            prevv[e.to]=v;
                            preve[e.to]=i;
                            update=true;
                        }
                    }
                }
            }
        }

        if(dist[t]==INF){
            return -1;
        }
        if(!isNegative){
            for(int v=0;v<N;v++) h[v]+=dist[v];
        }
        Weight d=f;
        for(int v=t;v!=s;v=prevv[v]){
            d=min(d,g[prevv[v]][preve[v]].cap);
        }
        f-=d;
        if(!isNegative){
            res+=d*h[t];
        }else{
            res+=d*dist[t];
        }
        for(int v=t;v!=s;v=prevv[v]){
            Edge& e=g[prevv[v]][preve[v]];
            e.cap-=d;
            g[v][e.rev].cap+=d;
        }
    }
    return res;
}
enum{HERO,WAR,CLE,MAGE,META};
enum{OUT,IN};
enum{S,T,WW,WC,WM};
const int SIZE=600;
int solve(int h,int w,int c,int m,int nw,int nc,int nm){
    map<tuple<int,int,int>,int> dic;
    int sz=0;
    auto getV=[&](int pro,int type,int v){
        auto x=make_tuple(pro,type,v);
        if(dic.count(x)) return dic[x];
        else return dic[x]=sz++;
    };
    Flow flow(SIZE);
    for(int i=0;i<h;i++){
        flow.addEdge(getV(META,OUT,S),getV(HERO,IN,i),1);
        flow.addEdge(getV(HERO,IN,i),getV(HERO,OUT,i),1);
        flow.addEdge(getV(HERO,OUT,i),getV(META,IN,WW),1);
    }
    for(int i=0;i<w;i++){
        flow.addEdge(getV(WAR,IN,i),getV(WAR,OUT,i),1);
        flow.addEdge(getV(WAR,OUT,i),getV(META,IN,WC),1);
    }
    
    for(int i=0;i<c;i++){
        flow.addEdge(getV(META,OUT,WW),getV(CLE,IN,i),1);
        flow.addEdge(getV(CLE,IN,i),getV(CLE,OUT,i),1);
        flow.addEdge(getV(CLE,OUT,i),getV(META,IN,WM),1);
    }
    for(int i=0;i<m;i++){
        flow.addEdge(getV(META,OUT,WC),getV(MAGE,IN,i),1);
        flow.addEdge(getV(MAGE,IN,i),getV(MAGE,OUT,i),1);
        flow.addEdge(getV(MAGE,OUT,i),getV(META,IN,T),1);
    }
    flow.addEdge(getV(META,IN,WW),getV(META,OUT,WW),nw);
    flow.addEdge(getV(META,IN,WC),getV(META,OUT,WC),nc);
    flow.addEdge(getV(META,IN,WM),getV(META,OUT,WM),nm);
    flow.addEdge(getV(META,OUT,WM),getV(META,IN,T),nm);
    
    
    for(int i=0;i<w;i++){
        int ni;
        cin>>ni;
        while(ni--){
            int hi;
            cin>>hi;
            hi--;
            flow.addEdge(getV(HERO,OUT,hi),getV(WAR,IN,i),1);
        }
    }
    for(int i=0;i<c;i++){
        int ni;
        cin>>ni;
        while(ni--){
            int wi;
            cin>>wi;
            wi--;
            flow.addEdge(getV(WAR,OUT,wi),getV(CLE,IN,i),1);
        }
    }
    for(int i=0;i<m;i++){
        int ni;
        cin>>ni;
        while(ni--){
            int ci;
            cin>>ci;
            ci--;
            flow.addEdge(getV(CLE,OUT,ci),getV(MAGE,IN,i),1);
        }
    }
    return flow.maxFlow(getV(META,OUT,S),getV(META,IN,T));
}
int main(){
    int h,w,c,m,nw,nc,nm;
    while(cin>>h>>w>>c>>m>>nw>>nc>>nm,h!=-1){
        cout<<solve(h,w,c,m,nw,nc,nm)<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3648
final_rank: 12

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

const int INF = 1e9;
struct Ford_fulkerson{
    struct edge{int to,cap,rev;};
    int n;
    vector<vector<edge> > graph;
    vector<int> vis;
    
    Ford_fulkerson(int _n):n(_n),graph(n),vis(n){}
    
    void addEdge(int from,int to,int cap){
        graph[from].push_back((edge){to,cap,(int)graph[to].size()});
        graph[to].push_back((edge){from,0,(int)graph[from].size()-1});
    }
    int dfs(int v,int t,int f){
        if(v==t)return f;
        vis[v]=true;
        for(int i=0;i<(int)graph[v].size();i++){
            edge& e = graph[v][i];
            if(!vis[e.to]&&e.cap>0){
                int d = dfs(e.to,t,min(f,e.cap));
                if(d>0){
                    e.cap-=d;
                    graph[e.to][e.rev].cap+=d;
                    return d;
                }
            }
        }
        return 0;
    }

    int maxFlow(int s,int t){
        int flow=0;
        for(;;){
            for(int i=0;i<n;i++)vis[i]=false;
            int f = dfs(s,t,INF);
            if(f==0)return flow;
            flow+=f;
        }
    }
    
};

int main(){
    int H,W,C,M,Nw,Nc,Nm;
    while(cin >> H >> W >> C >> M >> Nw >> Nc >> Nm){
        if(H==-1)break;
        int s = 0;
        int t = H+(W*2)+(C*2)+(M*2)+1;
        int nw1 = t+1,nw2=nw1+1;
        int nc1 = nw2+1,nc2=nc1+1;
        int nm1 = nc2+1,nm2=nm1+1;
        Ford_fulkerson ff(nm2+10);

        for(int i=1;i<=W;i++){
            int n;
            cin >> n;
            for(int j=0;j<n;j++){
                int k;
                cin >> k;
                ff.addEdge(k,H+i,1);//勇者ー＞戦士
            }
        }
        for(int i=1;i<=C;i++){
            int n;
            cin >> n;
            for(int j=0;j<n;j++){
                int k;
                cin >> k;
                ff.addEdge(H+W+k,H+(2*W)+i,1);//戦士ー＞僧侶
            }
        }
        for(int i=1;i<=M;i++){
            int n;
            cin >> n;
            for(int j=0;j<n;j++){
                int k;
                cin >> k;
                ff.addEdge(H+(2*W)+C+k,H+(2*W)+(2*C)+i,1);//僧侶ー＞魔法使い
            }
        }

        for(int i=1;i<=H;i++){
            ff.addEdge(s,i,1);//s->勇者
            ff.addEdge(i,nw1,1);//勇者ー＞戦士選ばない
        }
        ff.addEdge(nw1,nw2,Nw);//戦士選ばない組がNw組
        for(int i=1;i<=W;i++){
            ff.addEdge(H+i,H+W+i,1);//選抜
            ff.addEdge(H+W+i,nc1,1);//戦士ー＞僧侶選ばない
        }
        ff.addEdge(nc1,nc2,Nc);//僧侶選ばない組がNc組
        for(int i=1;i<=C;i++){
            ff.addEdge(nw2,H+(2*W)+i,1);//戦士選ばないー＞僧侶
            ff.addEdge(H+(2*W)+i,H+(2*W)+C+i,1);//選抜
            ff.addEdge(H+(2*W)+C+i,nm1,1);//僧侶ー＞魔法使い選ばない
        }
        ff.addEdge(nm1,nm2,Nm);//魔法使い選ばない組がNm組
        for(int i=1;i<=M;i++){
            ff.addEdge(nc2,H+(2*W)+(2*C)+i,1);//僧侶選ばないー＞魔法使い
            ff.addEdge(H+(2*W)+(2*C)+i,H+(2*W)+(2*C)+M+i,1);//選抜
            ff.addEdge(H+(2*W)+(2*C)+M+i,t,1);//魔法使いー＞t
        }
        ff.addEdge(nm2,t,Nm);

        cout << ff.maxFlow(s,t) << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3172
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(a) max((a),-(a))
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define repe(i,n) rep(i,(n)+1)
#define per(i,n) for(int i=(int)(n)-1;i>=0;i--)
#define pere(i,n) rep(i,(n)+1)
#define all(x) (x).begin(),(x).end()
#define SP <<" "<<
#define RET return 0
#define MOD 1000000007
#define INF 1000000000

typedef long long LL;
typedef long double LD;

class FordFulkerson{
  vector<vector<int>> e;
  vector<bool> usd;
  int n,s,t;
public:
  FordFulkerson(vector<vector<int>> &v,int ss,int tt){
    e=v,s=ss,t=tt,n=v.size();
  }
  int solve(){
    int ans=0,ret;
    usd=vector<bool>(n,false);
    while(1){
      usd=vector<bool>(n,false);
      ret=dfs(s);
      if(ret==0) break;
      else ans+=ret;
    }
    return ans;
  }
  int dfs(int x,int d=INF){
    usd[x]=true;
    int ret;
    for(int i=0;i<n;i++){
      if((!usd[i])&&e[x][i]>0){
        if(i==t){
          ret=min(d,e[x][i]);
          e[x][i]-=ret;
          e[i][x]+=ret;
          return ret;
        }else{
          ret=dfs(i,min(d,e[x][i]));
          if(ret>0){
            e[x][i]-=ret;
            e[i][x]+=ret;
            return ret;
          }
        }
      }
    }
    return 0;
  }
};

int main(){
  while(1){
    int h,w,c,m,nw,nc,nm;
    cin >> h >> w >> c >> m >> nw >> nc >> nm;
    if(h<0) return 0;
    int sz=308;
    vector<vector<int>> e(sz,vector<int>(sz,0));

    int ni,ch;
    for(int i=0;i<h;i++){
      e[sz-2][i]=1;
    }
    for(int i=0;i<w;i++){
      cin >> ni;
      for(int j=0;j<ni;j++){
        cin >> ch;
        e[ch-1][50+i]=1;
      }
      e[50+i][100+i]=1;
    }
    for(int i=0;i<c;i++){
      cin >> ni;
      for(int j=0;j<ni;j++){
        cin >> ch;
        e[100+ch-1][150+i]=1;
      }
      e[150+i][200+i]=1;
    }
    for(int i=0;i<m;i++){
      cin >> ni;
      for(int j=0;j<ni;j++){
        cin >> ch;
        e[200+ch-1][250+i]=1;
      }
      e[250+i][sz-1]=1;
    }
    e[301][302]=nw;
    e[303][304]=nc;
    e[305][sz-1]=nm;
    for(int i=0;i<h;i++){
      e[i][301]=1;
    }
    for(int i=0;i<c;i++){
      e[302][150+i]=1;
    }
    for(int i=0;i<w;i++){
      e[100+i][303]=1;
    }
    for(int i=0;i<m;i++){
      e[304][250+i]=1;
    }
    for(int i=0;i<c;i++){
      e[200+i][305]=1;
    }

    // for(int i=0;i<sz;i++){
    //   for(int j=0;j<sz;j++){
    //     cout << e[i][j] << " ";
    //   }
    //   cout << endl;
    // }

    FordFulkerson solver(e,sz-2,sz-1);
    cout << solver.solve() << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3624
final_rank: 17

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
template< typename flow_t >
struct Dinic {
  const flow_t INF;

  struct edge {
    int to;
    flow_t cap;
    int rev;
    bool isrev;
  };

  vector< vector< edge > > graph;
  vector< int > min_cost, iter;

  Dinic(int V) : INF(numeric_limits< flow_t >::max()), graph(V) {}

  void add_edge(int from, int to, flow_t cap) {
    graph[from].emplace_back((edge) {to, cap, (int) graph[to].size(), false});
    graph[to].emplace_back((edge) {from, 0, (int) graph[from].size() - 1, true});
  }

  bool bfs(int s, int t) {
    min_cost.assign(graph.size(), -1);
    queue< int > que;
    min_cost[s] = 0;
    que.push(s);
    while(!que.empty() && min_cost[t] == -1) {
      int p = que.front();
      que.pop();
      for(auto &e : graph[p]) {
        if(e.cap > 0 && min_cost[e.to] == -1) {
          min_cost[e.to] = min_cost[p] + 1;
          que.push(e.to);
        }
      }
    }
    return min_cost[t] != -1;
  }

  flow_t dfs(int idx, const int t, flow_t flow) {
    if(idx == t) return flow;
    for(int &i = iter[idx]; i < graph[idx].size(); i++) {
      edge &e = graph[idx][i];
      if(e.cap > 0 && min_cost[idx] < min_cost[e.to]) {
        flow_t d = dfs(e.to, t, min(flow, e.cap));
        if(d > 0) {
          e.cap -= d;
          graph[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return 0;
  }

  flow_t max_flow(int s, int t) {
    flow_t flow = 0;
    while(bfs(s, t)) {
      iter.assign(graph.size(), 0);
      flow_t f = 0;
      while((f = dfs(s, t, INF)) > 0) flow += f;
    }
    return flow;
  }

  void output() {
    for(int i = 0; i < graph.size(); i++) {
      for(auto &e : graph[i]) {
        if(e.isrev) continue;
        auto &rev_e = graph[e.to][e.rev];
        cout << i << "->" << e.to << " (flow: " << rev_e.cap << "/" << e.cap + rev_e.cap << ")" << endl;
      }
    }
  }
};

int main(void){
    int H,W,C,M,nw,nc,nm,i,j,k;
    while(cin >> H >> W >> C >> M >> nw >> nc >> nm){
        if(H==-1)break;
        Dinic< int > g(2*(H+W+C+M)+10);
        //Warrior
        for(int to=1;to<=W;to++){
            cin >> j;
            for(k=0;k<j;k++){
                int from;
                cin >> from;
                g.add_edge(from,to+H,1);
            }
        }
        for(i=1;i<=W;i++)g.add_edge(i+H,i+H+W,1);
        //cleric
        for(int to=1;to<=C;to++){
            cin >> j;
            for(k=0;k<j;k++){
                int from;
                cin >> from;
                g.add_edge(from+H+W,to+H+2*W,1);
            }
        }
        for(i=1;i<=C;i++)g.add_edge(i+H+2*W,i+H+2*W+C,1);
        //mage
        for(int to=1;to<=M;to++){
            cin >> j;
            for(k=0;k<j;k++){
                int from;
                cin >> from;
                g.add_edge(from+H+2*W+C,to+H+2*W+2*C,1);
            }
        }
        for(i=1;i<=M;i++)g.add_edge(H+2*W+2*C+i,H+2*W+2*C+M+1,1);//tailのedge
        
        for(i=1;i<=H;i++)g.add_edge(0,i,1);//最初のedge
        for(i=1;i<=H;i++)g.add_edge(i,H+2*W+2*C+M+2,1);//任意の勇者からwarriorを迂回するedge
        g.add_edge(H+2*W+2*C+M+2,H+2*W+2*C+M+3,nw);//warriorスルーできる数
        for(i=1;i<=C;i++)g.add_edge(H+2*W+2*C+M+3,H+2*W+i,1);//warrior迂回した後のedge
        for(i=1;i<=W;i++)g.add_edge(H+W+i,H+2*W+2*C+M+4,1);//clericを迂回するedge
        g.add_edge(H+2*W+2*C+M+4,H+2*W+2*C+M+5,nc);//clericスルーできる数
        for(i=1;i<=M;i++)g.add_edge(H+2*W+2*C+M+5,H+2*W+2*C+i,1);//迂回したあとのedge
        for(i=1;i<=C;i++)g.add_edge(H+2*W+C+i,H+2*W+2*C+M+6,1);//mageを迂回
        g.add_edge(H+2*W+2*C+M+6,H+2*W+2*C+M+1,nm);
        cout << g.max_flow(0,H+2*W+2*C+M+1) << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3184
final_rank: 4

code_snippet: #include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

//O(F|E|)
class FordFulkerson{
public:
	class edge{
	public:
		int to, cap, rev;
		edge(){};
		edge(int _to, int _cap, int _rev){
			to = _to;
			cap = _cap;
			rev = _rev;
		}
	};
	vector<vector<edge> >G;
	vector<int>used;
	FordFulkerson(int n){
		G.resize(n);
	}
	void addEdge(int from, int to, int cap){
		G[from].push_back(edge(to, cap, G[to].size()));
		G[to].push_back(edge(from, 0, G[from].size() - 1));
	}
	int dfs(int v, int t, int f){
		if (v == t)return f;
		used[v] = 1;
		for (int i = 0; i < G[v].size(); i++){
			edge &e = G[v][i];
			if ((!used[e.to]) && (e.cap > 0)){
				int d = dfs(e.to, t, min(f, e.cap));
				if (d > 0){
					e.cap -= d;
					G[e.to][e.rev].cap += d;
					return d;
				}
			}
		}
		return 0;
	}
	int maxFlow(int s, int t){
		int flow = 0;
		for (;;){
			used.clear();
			used.resize(G.size(), 0);
			int f = dfs(s, t, 1145141919);
			if (f == 0)return flow;
			flow += f;
		}
	}
};

int main(){
    for(int H, W, C, M, NW, NC, NM;cin>>H>>W>>C>>M>>NW>>NC>>NM;){
        if(H<0)break;
        FordFulkerson mf(310);
        for(int i=1;i<=H;i++)mf.addEdge(0, i, 1);
        for(int i=1;i<=H;i++)mf.addEdge(i, 301, 1);
        
        mf.addEdge(301, 302, NW);
        for(int i=51;i<=50+W;i++)mf.addEdge(i, i+50, 1);
        
        for(int i=101;i<=100+W;i++)mf.addEdge(i, 303, 1);
        
        mf.addEdge(303, 304, NC);
        for(int i=151;i<=150+C;i++)mf.addEdge(i, i+50, 1);
        for(int i=151;i<=150+C;i++)mf.addEdge(302, i, 1);
        
        for(int i=201;i<=200+C;i++)mf.addEdge(i, 305, 1);
        
        for(int i=251;i<=250+M;i++)mf.addEdge(304, i, 1);
        for(int i=251;i<=250+M;i++)mf.addEdge(i, 306, 1);
        mf.addEdge(305, 306, NM);

        for(int i=1;i<=W;i++){
            int n;
            cin>>n;
            for(int j=1;j<=n;j++){
                int h;
                cin>>h;
                mf.addEdge(h, 50+i, 1);
            }
        }
        for(int i=1;i<=C;i++){
            int n;
            cin>>n;
            for(int j=1;j<=n;j++){
                int w;
                cin>>w;
                mf.addEdge(100+w, 150+i, 1);
            }
        }
        for(int i=1;i<=M;i++){
            int n;
            cin>>n;
            for(int j=1;j<=n;j++){
                int c;
                cin>>c;
                mf.addEdge(200+c, 250+i, 1);
            }
        }
        cout << mf.maxFlow(0, 306) << endl; 
    }
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3212
final_rank: 6

code_snippet: #include<iomanip>
#include<limits>
#include<thread>
#include<utility>
#include<iostream>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<numeric>
#include<cassert>
#include<random>
#include<chrono>
#include<unordered_map>
#include<fstream>
#include<list>
#include<typeinfo>
#include<functional>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef pair<int,int> pi;
typedef pair<double,double> pd;
typedef pair<double,ll> pdl;
#define F first
#define S second
const ll E=1e18+7;
const ll MOD=1000000007;



class Flow{
private:
    struct edge{
        ll to;
        ll cap;
        ll rev;
    };
    
    ll INF;
    ll v;
    vector<vector<edge>> e;
    vector<bool> used;
    
    void reset_used(){
        for(int i=0;i<used.size();i++){used[i]=false;}
    }
    
    ll dfs(ll where,ll to,ll flow){
        if(where==to){return flow;}
        used[where]=true;
        for(int i=0;i<e[where].size();i++){
            edge &E=e[where][i];
            if(!used[E.to] && E.cap>0){
                ll d=dfs(E.to,to,min(flow,E.cap));
                if(d>0){
                    E.cap-=d;
                    e[E.to][E.rev].cap+=d;
                    return d;
                }
            }
        }
        return 0;
    }
    
public:
    Flow(ll v):v(v){
        e.resize(v);
        used.resize(v,false);
        INF=1e18+7;
    }
    
    void add_edge(ll from,ll to,ll cap){
        e[from].push_back((edge){to,cap,(ll)e[to].size()});
        e[to].push_back((edge){from,0,(ll)e[from].size()-1});
    }
    
    ll max_flow(ll s,ll t){
        vector<vector<edge>> ed=e;
        ll flow=0;
        while(1){
            reset_used();
            ll f=dfs(s,t,INF);
            if(f==0){break;}
            flow+=f;
        }
        e=ed;
        return flow;
    }
};



    
int main(){
    const ll INF=1e18;
    ll h,w,c,m,nw,nc,nm;
    while(cin>>h>>w>>c>>m>>nw>>nc>>nm && h!=-1){
        Flow F((h+w+c+m+20)*2);
        ll s=(h+w+c+m+20)*2; s--;
        ll g=s-1;
        ll NW=g-1;
        ll INW=NW-1;
        ll NC=INW-1;
        ll INC=NC-1;
        ll NM=INC-1;
        ll INM=NM-1;
        F.add_edge(INW,NW,nw);
        //F.add_edge(NW,INC,INF);
        F.add_edge(INC,NC,nc);
        //F.add_edge(NC,INM,INF);
        F.add_edge(INM,NM,nm);
        F.add_edge(NM,g,INF);
        for(int i=0;i<h;i++){
            F.add_edge(s,i,1);
            F.add_edge(i,INW,1);
        }
        for(int i=0;i<w;i++){
            F.add_edge(h+i,h+w+i,1);
            F.add_edge(h+w+i,INC,1);
            ll n;
            cin>>n;
            for(int t=0;t<n;t++){
                ll H;
                cin>>H;
                F.add_edge(H-1,h+i,1);
            }
        }
        for(int i=0;i<c;i++){
            F.add_edge(h+2*w+i,h+2*w+c+i,1);
            F.add_edge(h+2*w+c+i,INM,1);
            F.add_edge(NW,h+2*w+i,1);
            ll n;
            cin>>n;
            for(int t=0;t<n;t++){
                ll H;
                cin>>H;
                F.add_edge(h+w+H-1,h+2*w+i,1);
            }
        }
        for(int i=0;i<m;i++){
            F.add_edge(h+2*w+2*c+i,h+2*w+2*c+m+i,1);
            F.add_edge(h+2*w+2*c+m+i,g,1);
            F.add_edge(NC,h+2*w+2*c+i,1);
            ll n;
            cin>>n;
            for(int t=0;t<n;t++){
                ll H;
                cin>>H;
                F.add_edge(h+2*w+c+H-1,h+2*w+2*c+i,1);
            }
        }
        cout<<F.max_flow(s,g)<<endl;
    }
    
    
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3664
final_rank: 13

code_snippet: #include <bits/stdc++.h>
#define r(i,n) for(int i=0;i<n;i++)
using namespace std;

struct Dinic{
  const int INF=1<<28;
  
  struct edge {
    int to,cap,rev;
    edge(){}
    edge(int to,int cap,int rev):to(to),cap(cap),rev(rev){}
  };

  int n;
  vector<vector<edge> > G;
  vector<map<int,int> > M;
  vector<int> level,iter;

  Dinic(){}
  Dinic(int sz):n(sz),G(n),M(n),level(n),iter(n){}
  
  void add_edge(int from,int to,int cap){
    M[from][to]=G[from].size();
    M[to][from]=G[to].size();
    G[from].push_back(edge(to,cap,G[to].size()));
    // undirected
    //G[to].push_back(edge(from,cap,G[from].size()-1));
    // directed
    G[to].push_back(edge(from,0,G[from].size()-1));
  }
  
  void bfs(int s){
    fill(level.begin(),level.end(),-1);
    queue<int> que;
    level[s]=0;
    que.push(s);
    while(!que.empty()){
      int v=que.front();que.pop();
      for(int i=0;i<(int)G[v].size();i++){
        edge &e = G[v][i];
        if(e.cap>0&&level[e.to]<0){
          level[e.to]=level[v]+1;
          que.push(e.to);
        }
      }
    }
  }
  
  int dfs(int v,int t,int f){
    if(v==t) return f;
    for(int &i=iter[v];i<(int)G[v].size();i++){
      edge &e=G[v][i];
      if(e.cap>0&&level[v]<level[e.to]){
        int d = dfs(e.to,t,min(f,e.cap));
	     if(d>0){
	       e.cap-=d;
	       G[e.to][e.rev].cap+=d;
	       return d;
	     }
      }
    }
    return 0;
  }
  
  int flow(int s,int t,int lim){
    int fl=0;
    for(;;){
      bfs(s);
      if(level[t]<0||lim==0) return fl;
      fill(iter.begin(),iter.end(),0);
      int f;
      while((f=dfs(s,t,lim))>0){
	     fl+=f;
	     lim-=f;
      }
    }
  }

  int flow(int s,int t){
    return flow(s,t,INF);
  }

  //cap==1 only
  bool back_edge(int s,int t,int from, int to){
    for(int i=0;i<(int)G[from].size();i++) {
      edge& e=G[from][i];
      if(e.to==to) {
        if(e.cap==0&&flow(from,to,1)==0) {
          flow(from,s,1);
          flow(t,to,1);
          return 1;
        }
      }
    }
    return 0;
  }
};

int A,B,C,D,NB,NC,ND,x,y,z;

int main(){
	while(cin>>A>>B>>C>>D>>NB>>NC>>ND,A!=-1){
		Dinic DIN(500);
		map<int,int>Ai,Bi,Ci,Di,Bp,Cp;  // number -> id;
		int id=0;
		r(i,A)Ai[i]=id++;
		r(i,B)Bp[i]=id++;
		r(i,B)Bi[i]=id++;
		r(i,C)Cp[i]=id++;
		r(i,C)Ci[i]=id++;
		r(i,D)Di[i]=id++;
		r(i,B){
			cin>>x;
			while(x--){
				cin>>y;
				y--;
				DIN.add_edge(Ai[y],Bp[i],1);
			}
		}
		r(i,C){
			cin>>x;
			while(x--){
				cin>>y;
				y--;
				DIN.add_edge(Bi[y],Cp[i],1);
			}
		}
		r(i,D){
			cin>>x;
			while(x--){
				cin>>y;
				y--;
				DIN.add_edge(Ci[y],Di[i],1);
			}
		}
		r(i,B){
			DIN.add_edge(Bp[i],Bi[i],1);
		}
		r(i,C){
			DIN.add_edge(Cp[i],Ci[i],1);
		}

		r(i,A)r(j,C){
			DIN.add_edge(Ai[i],id,1);
			if(!i)DIN.add_edge(id+1,Cp[j],1);
		}
		DIN.add_edge(id,id+1,NB); id+=2;
		r(i,B)r(j,D){
			DIN.add_edge(Bi[i],id,1);
			if(!i)DIN.add_edge(id+1,Di[j],1);
		}
		DIN.add_edge(id,id+1,NC); id+=2;
		int source=id,sink=id+1; id+=2;
		r(j,C){
			DIN.add_edge(Ci[j],id,1);
		}
		DIN.add_edge(id,sink,ND);
		r(i,A)DIN.add_edge(source,i,1);
		r(i,D)DIN.add_edge(Di[i],sink,1);
		cout<<DIN.flow(source,sink)<<endl;
	}
}
accuracy: 1
time_ms: 20
memory_kb: 4080
final_rank: 18

code_snippet: #include <bits/stdc++.h>
#define ll long long
#define INF 1000000005
#define MOD 1000000007
#define EPS 1e-10
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define rrep(i,n) for(int i=(int)(n)-1;i>=0;--i)
#define srep(i,s,t) for(int i=(int)(s);i<(int)(t);++i)
#define each(a,b) for(auto& (a): (b))
#define all(v) (v).begin(),(v).end()
#define len(v) (int)(v).size()
#define zip(v) sort(all(v)),v.erase(unique(all(v)),v.end())
#define cmx(x,y) x=max(x,y)
#define cmn(x,y) x=min(x,y)
#define fi first
#define se second
#define pb push_back
#define show(x) cout<<#x<<" = "<<(x)<<endl
#define spair(p) cout<<#p<<": "<<p.fi<<" "<<p.se<<endl
#define sar(a,n) cout<<#a<<":";rep(kbrni,n)cout<<" "<<a[kbrni];cout<<endl
#define svec(v) cout<<#v<<":";rep(kbrni,v.size())cout<<" "<<v[kbrni];cout<<endl
#define svecp(v) cout<<#v<<":";each(kbrni,v)cout<<" {"<<kbrni.first<<":"<<kbrni.second<<"}";cout<<endl
#define sset(s) cout<<#s<<":";each(kbrni,s)cout<<" "<<kbrni;cout<<endl
#define smap(m) cout<<#m<<":";each(kbrni,m)cout<<" {"<<kbrni.first<<":"<<kbrni.second<<"}";cout<<endl

using namespace std;

typedef pair<int,int> P;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<double> vd;
typedef vector<P> vp;
typedef vector<string> vs;

const int MAX_N = 100005;

template<typename T> class PushRelabel{
private:
    struct edge{
        int to,rev;
        T f,cap;
    };
    vector<vector<edge> > G;
    int V;
public:
    PushRelabel(int node_size){
        V = node_size;
        G.resize(V);
    }
    void add_edge(int from,int to,T capacity){
        G[from].push_back((edge){to,(int)G[to].size(),(T)0,capacity});
        G[to].push_back((edge){from,(int)G[from].size()-1,(T)0,(T)0});
    }
    T solve(int s,int t){
        vector<int> d(V,0),mxd(V,0);
        vector<T> ex(V,0);
        d[s] = V-1;
        for(edge& e : G[s]){
            e.f = e.cap;
            G[e.to][e.rev].f = -e.cap;
            ex[e.to] += e.cap;
        }
        for(int sz = 0;;){
            if(sz == 0){
                rep(i,V){
                    if(i != s && i != t && ex[i] > 0){
                        if(sz != 0 && d[i] > d[mxd[0]]){
                            sz = 0;
                        }
                        mxd[sz++] = i;
                    }
                }
            }
            if(sz == 0) break;
            while(sz){
                int i = mxd[sz-1];
                bool push = false;
                for(int j = 0; j < (int)G[i].size() && ex[i] != 0; j++){
                    edge& e = G[i][j];
                    if(d[i] == d[e.to] + 1 && e.cap - e.f > 0){
                        //push操作
                        push = true;
                        T df = min(e.cap - e.f, ex[i]);
                        e.f += df, G[e.to][e.rev].f -= df;
                        ex[i] -= df, ex[e.to] += df;
                        if(ex[i] == 0){
                            sz--;
                        }
                    }
                }
                if(!push){
                    //relabel操作
                    d[i] = numeric_limits<int>::max();
                    for(edge& e : G[i]){
                        if(d[i] > d[e.to] + 1 && e.cap - e.f > 0){
                            d[i] = d[e.to] + 1;
                        }
                    }
                    if(d[i] > d[mxd[0]]){
                        sz = 0;
                        break;
                    }
                }
            }
        }
        T flow = 0;
        for(edge& e : G[s]){
            flow += e.f;
        }
        return flow;
    }
};

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    while(1){
        int h,w,c,m,nw,nc,nm;
        cin >> h >> w >> c >> m >> nw >> nc >> nm;
        if(h == -1){
            break;
        }
        int al = h+2*w+2*c+m;
        PushRelabel<int> d(al+7);
        rep(i,h){
            d.add_edge(al,i,1);
        }
        rep(i,w){
            int n;
            cin >> n;
            rep(j,n){
                int ag;
                cin >> ag;
                --ag;
                d.add_edge(ag,i+h,1);
            }
            d.add_edge(h+i,h+w+i,1);
        }
        rep(i,c){
            int n;
            cin >> n;
            rep(j,n){
                int ag;
                cin >> ag;
                --ag;
                d.add_edge(h+w+ag,h+2*w+i,1);
            }
            d.add_edge(h+2*w+i,h+2*w+c+i,1);
        }
        rep(i,m){
            int n;
            cin >> n;
            rep(j,n){
                int ag;
                cin >> ag;
                --ag;
                d.add_edge(ag+h+2*w+c,h+2*w+2*c+i,1);
            }
            d.add_edge(h+2*w+2*c+i,al+1,1);
        }
        rep(i,h){
            d.add_edge(i,al+2,1);
        }
        d.add_edge(al+2,al+3,nw);
        rep(i,c){
            d.add_edge(al+3,h+2*w+i,1);
        }
        rep(i,w){
            d.add_edge(h+w+i,al+4,1);
        }
        d.add_edge(al+4,al+5,nc);
        rep(i,m){
            d.add_edge(al+5,h+2*w+2*c+i,1);
        }
        rep(i,c){
            d.add_edge(h+2*w+c+i,al+6,1);
        }
        d.add_edge(al+6,al+1,nm);
        cout << d.solve(al,al+1) << "\n";
    }
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3160
final_rank: 19

code_snippet: #include <bits/stdc++.h>
#define INF 1e9
#define MAX_V 10000
using namespace std;

/*?????§?????¢?????´?????????(Ford_Fulerson????????¨)???O(F|E|)*/

//????????¨????§???????(???????????????????????????)
struct edge{int to, cap, rev;};

vector<edge> G[MAX_V]; //??°???????????£??\?????????
bool used[MAX_V];      //DFS??§?????§??????????????????????????°

void init(){
  for(int i=0;i<MAX_V;i++) G[i].clear();
}

//from??????to??????????????????cap???????????°?????????????????????
void add_edge(int from,int to,int cap){
  G[from].push_back((edge){to,cap,(int)G[to].size()});
  G[to].push_back((edge){from,0,(int)G[from].size()-1});  
}

//?¢?????????????DFS??§??¢???
int dfs(int v,int t,int f){
  if(v == t)return f;
  used[v]=true;
  for(int i=0; i<G[v].size() ;i++){
    edge &e = G[v][i];
    if(!used[e.to] && e.cap > 0){
      int d = dfs(e.to ,t , min(f,e.cap));
      if(d > 0){
	e.cap -= d;
	G[e.to][e.rev].cap += d;
	return d;
      }
    }
  }
  return 0;
}

//s??????t???????????§???????±???????
int max_flow(int s,int t){
  int flow = 0;
  for(;;){
    memset(used,0,sizeof(used));
    int f = dfs(s, t, INF);
    if(f == 0)return flow;
    flow += f;
  }
}

int main(){
  
  int H, W, C, M, Nw, Nc, Nm;
  
  while(1){
    
    cin>>H>>W>>C>>M>>Nw>>Nc>>Nm;
    if(H==-1) break;

    init();
    
    int s=0;
    int Hws=(H+W+C+M)*2+1, Hwt=Hws+1;
    int Hcs=Hwt+1, Hct=Hcs+1;
    int Hms=Hct+1, Hmt=Hms+1;
    int t=Hmt+1;

    for(int i=1;i<=H;i++){
      add_edge(s,i*2-1,1);
      add_edge(i*2-1,i*2,1);
      add_edge(i*2,Hws,1);
    }
    
    for(int i=1;i<=W;i++){
      int n;
      cin>>n;
      add_edge((H+i)*2-1,(H+i)*2,1);
      add_edge((H+i)*2,Hcs,1);
      for(int j=0;j<n;j++){
	int a;
	cin>>a;
	add_edge(a*2,(H+i)*2-1,1);
      }
    }
    
    for(int i=1;i<=C;i++){
      int n;
      cin>>n;
      add_edge(Hwt,(H+W+i)*2-1,INF);
      add_edge((H+W+i)*2-1,(H+W+i)*2,1);
      add_edge((H+W+i)*2,Hms,1);
      for(int j=0;j<n;j++){
	int a;
	cin>>a;
	add_edge((H+a)*2,(H+W+i)*2-1,1);
      }
    }
    
    for(int i=1;i<=M;i++){
      int n;
      cin>>n;
      add_edge(Hct,(H+W+C+i)*2-1,INF);
      add_edge((H+W+C+i)*2-1,(H+W+C+i)*2,1);
      add_edge((H+W+C+i)*2,t,1);
      for(int j=0;j<n;j++){
	int a;
	cin>>a;
	add_edge((H+W+a)*2,(H+W+C+i)*2-1,1);
      }
    }

    add_edge(Hws,Hwt,Nw);
    add_edge(Hcs,Hct,Nc);
    add_edge(Hms,Hmt,Nm);
    add_edge(Hmt,t,INF);
    
    cout<<max_flow(s, t)<<endl;
  }
  
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3424
final_rank: 11