//自分で作っといて何だが //誰だこんな問題作ったやつ! #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; static const double EPS = 1e-8; static const double PI = 4.0 * atan(1.0); static const double PI2 = 8.0 * atan(1.0); typedef long long ll; typedef vector Array; typedef vector Matrix; int maxFlow(Matrix& capacity, int s, int t) { const int n = capacity.size(); int result = 0; for (;;){ vector open; open.push_back(s); vector prev(n, -1); while (!open.empty() && prev[t] == -1){ const int from = open.back(); open.pop_back(); for (int to = 0; to < n; ++to){ if (prev[to] >= 0 || !capacity[from][to]){ continue; } prev[to] = from; open.push_back(to); } } if (prev[t] == -1){ break; } vector path; path.push_back(t); int flow = INT_MAX; while (path.back() != s){ flow = min(flow, capacity[prev[path.back()]][path.back()]); path.push_back(prev[path.back()]); } for (int i = 0; i < path.size() - 1; ++i){ capacity[path[i + 1]][path[i]] -= flow; capacity[path[i]][path[i + 1]] += flow; } result += flow; } return result; } int getSouce() { return 0; } int getHero(int h) { return h + 1; } int getFighter(int H, int f, int leftRight) { return getHero(H) + f * 2 + leftRight; } int getFighterSkip(int H, int F, int leftRight) { return getFighter(H, F, 0) + leftRight; } int getPriest(int H, int F, int p, int leftRight) { return getFighterSkip(H, F, 0) + 2 + p * 2 + leftRight; } int getPriestSkip(int H, int F, int P, int leftRight) { return getPriest(H, F, P, 0) + leftRight; } int getWizard(int H, int F, int P, int w) { return getPriestSkip(H, F, P, 0) + 2 + w; } int getWizardSkip(int H, int F, int P, int W) { return getWizard(H, F, P, W); } int getSink(int H, int F, int P, int W) { return getWizardSkip(H, F, P, W) + 1; } static const int MAX = 0xfffffff; enum { LEFT, RIGHT }; int main() { for (int H, F, P, W, MF, MP, MW; cin >> H >> F >> P >> W >> MF >> MP >> MW; ){ const int N = getSink(H, F, P, W) + 1; Matrix m(N, Array(N)); //ソース→勇者 for (int h = 0; h < H; ++h){ m[getSouce()][getHero(h)] = 1; } //勇者→戦士外し for (int h = 0; h < H; ++h){ m[getHero(h)][getFighterSkip(H, F, LEFT)] = 1; } //勇者→戦士 for (int f = 0; f < F; ++f){ int n; cin >> n; for (int i = 0; i < n; ++i){ int h; cin >> h; --h; m[getHero(h)][getFighter(H, f, LEFT)] = 1; } } //戦士外し→戦士外し m[getFighterSkip(H, F, LEFT)][getFighterSkip(H, F, RIGHT)] = MF; //戦士→戦士 for (int f = 0; f < F; ++f){ m[getFighter(H, f, LEFT)][getFighter(H, f, RIGHT)] = 1; } //戦士外し→僧侶 for (int p = 0; p < P; ++p){ m[getFighterSkip(H, F, RIGHT)][getPriest(H, F, p, LEFT)] = 1; } //戦士→僧侶 for (int p = 0; p < P; ++p){ int n; cin >> n; for (int i = 0; i < n; ++i){ int f; cin >> f; --f; m[getFighter(H, f, RIGHT)][getPriest(H, F, p, LEFT)] = 1; } } //戦士→僧侶外し for (int f = 0; f < F; ++f){ m[getFighter(H, f, RIGHT)][getPriestSkip(H, F, P, LEFT)] = 1; } //僧侶外し→僧侶外し m[getPriestSkip(H, F, P, LEFT)][getPriestSkip(H, F, P, RIGHT)] = MP; //僧侶→僧侶 for (int p = 0; p < P; ++p){ m[getPriest(H, F, p, LEFT)][getPriest(H, F, p, RIGHT)] = 1; } //僧侶外し→魔法使い for (int w = 0; w < W; ++w){ m[getPriestSkip(H, F, P, RIGHT)][getWizard(H, F, P, w)] = 1; } //僧侶→魔法使い for (int w = 0; w < W; ++w){ int n; cin >> n; for (int i = 0; i < n; ++i){ int p; cin >> p; --p; m[getPriest(H, F, p, RIGHT)][getWizard(H, F, P, w)] = 1; } } //僧侶→魔法使い外し for (int p = 0; p < P; ++p){ m[getPriest(H, F, p, RIGHT)][getWizardSkip(H, F, P, W)] = 1; } //魔法使い外し→シンク m[getWizardSkip(H, F, P, W)][getSink(H, F, P, W)] = MW; //魔法使い→シンク for (int w = 0; w < W; ++w){ m[getWizard(H, F, P, w)][getSink(H, F, P, W)] = 1; } cout << maxFlow(m, getSouce(), getSink(H, F, P, W)) << endl; } }