Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma GCC optimize("Ofast,unroll-loops")
- #include <bits/stdc++.h>
- #define sz(a) ((int)(a).size())
- #define all(a) (a).begin(), (a).end()
- #define fi first
- #define se second
- using namespace std;
- #ifndef LOCAL
- #define endl '\n'
- #endif
- typedef long long ll;
- typedef pair<int, int> pii;
- const int NMAX = 4005;
- const int INF = 2e9+5;
- struct Edge {
- int dest, flow, rev;
- };
- int n, s, r, f, t;
- vector<Edge> g[NMAX];
- int d[NMAX], last[NMAX];
- unordered_map<string, int> mp;
- vector<int> v[NMAX];
- void io() {
- #ifdef LOCAL
- freopen("input.txt", "r", stdin);
- #else
- ios_base::sync_with_stdio(false);
- cin.tie(0);
- cout.tie(0);
- #endif
- }
- void read() {
- cin >> s >> r >> f >> t;
- string str;
- for (int i = 1; i <= r; i++) {
- cin >> str;
- mp[str] = i;
- }
- for (int i = 1; i <= f; i++) {
- cin >> str;
- mp[str] = r + i;
- }
- n = r + f;
- for (int i = 1, cnt; i <= t; i++) {
- cin >> cnt;
- v[i].reserve(cnt);
- while (cnt--) {
- cin >> str;
- if (mp[str] == 0)
- mp[str] = ++n;
- v[i].push_back(mp[str]);
- }
- }
- }
- void add_edge(int x, int y, int c) {
- g[x].push_back({ y, c, sz(g[y]) });
- g[y].push_back({ x, 0, sz(g[x]) - 1 });
- }
- void precalc() {
- for (int i = 1; i <= t; i++) {
- add_edge(n + 1, n + 2, 1);
- n += 2;
- }
- for (int i = 1; i <= t; i++) {
- for (auto &it : v[i]) {
- add_edge(it, s + (i << 1) - 1, 1);
- if (it > r)
- add_edge(s + (i << 1), it, 1);
- }
- }
- n++;
- for (int i = 1; i <= r; i++)
- add_edge(0, i, 1);
- for (int i = 1; i <= f; i++)
- add_edge(r + i, n, 1);
- }
- bool bfs() {
- memset(d, 0, sizeof(d));
- memset(last, 0, sizeof(last));
- queue<int> q;
- q.push(0);
- d[0] = 1;
- while (!q.empty()) {
- int u = q.front();
- q.pop();
- if (u == n) continue;
- for (auto &it : g[u]) {
- if (!d[it.dest] && it.flow > 0) {
- d[it.dest] = d[u] + 1;
- q.push(it.dest);
- }
- }
- }
- return d[n];
- }
- int dfs(int x = 0, int flow = INF) {
- if (x == n) return flow;
- for (; last[x] < sz(g[x]); last[x]++) {
- Edge &e = g[x][last[x]];
- if (e.flow > 0 && d[e.dest] == d[x] + 1) {
- if (int ret = dfs(e.dest, min(flow, e.flow))) {
- e.flow -= ret;
- g[e.dest][e.rev].flow += ret;
- return ret;
- }
- }
- }
- return 0;
- }
- int dinic() {
- int max_flow = 0;
- while (bfs()) {
- while (int flow = dfs())
- max_flow += flow;
- }
- return max_flow;
- }
- signed main() {
- io();
- read();
- precalc();
- cout << dinic() << endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement