an alternating path is a path that begins with an unmatched vertex and whose edges belong alternately to the matching and not to the matching.
an augmenting path is an alternating path that starts from and ends on free (unmatched) vertices.
Traverse all the points on the left, for each point \(u\) if we can find a augmenting path \(\vec{p}\) starting from \(u\), then we use the edges of \(\vec{p}\) to update the matches of each point on \(\vec{p}\).
constint MAXN = 128; vector<int> g[MAXN]; int match[MAXN]; bool vis[MAXN];
voidinit(int n, int m){ for (int i = 1; i <= m; i++) { g[i].clear(); } fill(match + 1, match + 1 + n, -1); }
voidadd(int u, int v){ g[u].push_back(v); }
booldfs(int u){ for (auto v : g[u]) { if (vis[v]) continue; vis[v] = true; if (match[v] == -1 || dfs(match[v])) { match[v] = u; returntrue; } } returnfalse; }
inthungary(int n, int m){ int ans = 0; for (int i = 1; i <= m; i++) { fill(vis + 1, vis + 1 + n, false); if (dfs(i)) ans++; } return ans; }
intmain(int argc, char **argv){ int n, m; while (scanf("%d%d", &n, &m) != EOF) { init(n, m); for (int i = 1; i <= m; i++) { int c; scanf("%d", &c); for (int j = 0; j < c; j++) { int v; scanf("%d", &v); add(i, v); } } printf("%d\n", hungary(n, m)); } return0; }
vector<int> g[MAXN]; int match[MAXN]; bool vis[MAXN];
voidadd(int u, int v){ g[u].push_back(v); }
voidinit(int n, int m){ for (int i = 1; i <= n + m; i++) { g[i].clear(); } fill(match + 1, match + 1 + n, -1); }
booldfs(int u){ for (auto v : g[u]) { if (vis[v]) continue; vis[v] = true; if (match[v] == -1 || dfs(match[v])) { match[v] = u; returntrue; } } returnfalse; }
inthungarian(int n, int m){ int ans = 0; for (int u = n + 1; u <= n + m; u++) { fill(vis + 1, vis + 1 + n, false); if (dfs(u)) ans++; } return ans; }
intmain(int argc, char **argv){ int n, m; while (scanf("%d%d", &n, &m) != EOF) { init(n, m); for (int u = n + 1; u <= n + m; u++) { int c; scanf("%d", &c); for (int j = 0; j < c; j++) { int v; scanf("%d", &v); add(u, v); add(v, u); } } printf("%d\n", hungarian(n, m)); } return0; }
vector<int> g[MAXN]; int match[MAXN]; bool vis[MAXN];
voidinit(int n, int m){ for (int i = 1; i <= n + m; i++) { g[i].clear(); } fill(match + 1, match + 1 + n + m, -1); }
booldfs(int u){ for (auto v : g[u]) { if (vis[v]) continue; vis[v] = true; if (match[v] == -1 || dfs(match[v])) { match[v] = u; returntrue; } } returnfalse; }
inthungarian(int n, int m){ int ans = 0; for (int u = 1; u <= n + m; u++) { fill(vis + 1, vis + 1 + n + m, false); if (dfs(u)) ans++; } return ans / 2; }
voidadd(int u, int v){ g[u].push_back(v); }
intmain(int argc, char **argv){ int n, m; while (scanf("%d%d", &n, &m) != EOF) { init(n, m); for (int u = n + 1; u <= n + m; u++) { int c; scanf("%d", &c); for (int j = 0; j < c; j++) { int v; scanf("%d", &v); add(u, v); add(v, u); } } printf("%d\n", hungarian(n, m)); } return0; }