#include <bits/stdc++.h> using namespace std; struct augment_path { vector<vector<int> > g; vector<int> pa; // 匹配 vector<int> pb; vector<int> vis; // 访问 int n, m; // 顶点和边的数量 int dfn; // 时间戳记 int res; // 匹配数 augment_path(int _n, int _m) : n(_n), m(_m) { assert(0 <= n && 0 <= m); pa = vector<int>(n, -1); pb = vector<int>(m, -1); vis = vector<int>(n); g.resize(n); res = 0; dfn = 0; } void add(int from, int to) { assert(0 <= from && from < n && 0 <= to && to < m); g[from].push_back(to); } bool dfs(int v) { vis[v] = dfn; for (int u : g[v]) { if (pb[u] == -1) { pb[u] = v; pa[v] = u; return true; } } for (int u : g[v]) { if (vis[pb[u]] != dfn && dfs(pb[u])) { pa[v] = u; pb[u] = v; return true; } } return false; } int solve() { while (true) { dfn++; int cnt = 0; for (int i = 0; i < n; i++) { if (pa[i] == -1 && dfs(i)) { cnt++; } } if (cnt == 0) { break; } res += cnt; } return res; } }; int main() { int n, m, e; cin >> n >> m >> e; augment_path solver(n, m); int u, v; for (int i = 0; i < e; i++) { cin >> u >> v; u--, v--; solver.add(u, v); } cout << solver.solve() << "\n"; for (int i = 0; i < n; i++) { cout << solver.pa[i] + 1 << " "; } cout << "\n"; }
选最多的点,满足两两之间没有边相连。
二分图中,最大独立集 = n - 最大匹配。
选最少的点,满足每条边至少有一个端点被选,不难发现补集是独立集。
二分图中,最小点覆盖 = n - 最大独立集。