用到了二分图的一些性质, 最大匹配数=最小点覆盖
貌似在白书上有讲
还不是很懂, 自己看着别人的博客用网络流写了一遍
反正以后学白书应该会系统学二分图的,紫书上没讲深。
目前就这样吧。
#include<cstdio> #include<vector> #include<cstring> #include<queue> #include<algorithm> #define REP(i, a, b) for(int i = (a); i < (b); i++) using namespace std; const int MAXN = 21234; const int MAXM = 112; struct Edge{ int from, to, cap, flow; }; vector<Edge> edges; vector<int> g[MAXN]; int cur[MAXN], h[MAXN]; int n, m, s, t; int map[MAXM][MAXM], c[MAXM][MAXM], r[MAXM][MAXM]; void AddEdge(int from, int to, int cap) { edges.push_back(Edge{from, to, cap, 0}); edges.push_back(Edge{to, from, 0, 0}); g[from].push_back(edges.size() - 2); g[to].push_back(edges.size() - 1); } bool bfs() { queue<int> q; q.push(s); memset(h, 0, sizeof(h)); h[s] = 1; while(!q.empty()) { int x = q.front(); q.pop(); REP(i, 0, g[x].size()) { Edge& e = edges[g[x][i]]; if(e.cap > e.flow && !h[e.to]) { h[e.to] = h[x] + 1; q.push(e.to); } } } return h[t]; } int dfs(int x, int a) { if(x == t || a == 0) return a; int flow = 0, f; for(int& i = cur[x]; i < g[x].size(); i++) { Edge& e = edges[g[x][i]]; if(h[x] + 1 == h[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0) { e.flow += f; edges[g[x][i] ^ 1].flow -= f; flow += f; if((a -= f) == 0) break; } } return flow; } int maxflow() { int flow = 0; while(bfs()) { memset(cur, 0, sizeof(cur)); flow += dfs(s, 1e9); } return flow; } void make_edges() { int cnt = 0, tmp; REP(i, 0, n) { bool ok = true; REP(j, 0, m) { if(map[i][j] == 1) { if(ok) cnt++; r[i][j] = cnt; ok = false; } else if(map[i][j] == 2) ok = true; } } tmp = cnt; REP(j, 0, m) { bool ok = true; REP(i, 0, n) { if(map[i][j] == 1) { if(ok) cnt++; c[i][j] = cnt; ok = false; } else if(map[i][j] == 2) ok = true; } } REP(i, 1, cnt + 5) g[i].clear(); s = cnt + 3, t = s + 1; REP(i, 1, tmp + 1) AddEdge(s, i, 1); REP(i, tmp + 1, cnt + 1) AddEdge(i, t, 1); REP(i, 0, n) REP(j, 0, m) if(map[i][j] == 1) AddEdge(r[i][j], c[i][j], 1); } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); edges.clear(); memset(map, 0, sizeof(map)); memset(c, 0, sizeof(c)); memset(r, 0, sizeof(r)); int tmp, x, y; scanf("%d", &tmp); while(tmp--) { scanf("%d%d", &x, &y); x--; y--; map[x][y] = 1; } scanf("%d", &tmp); while(tmp--) { scanf("%d%d", &x, &y); x--; y--; map[x][y] = 2; } make_edges(); printf("%d\n", maxflow()); } return 0; }