当前位置: 代码迷 >> 综合 >> 紫书 习题 11-9 UVa 12549 (二分图最小点覆盖)
  详细解决方案

紫书 习题 11-9 UVa 12549 (二分图最小点覆盖)

热度:61   发布时间:2023-09-20 21:16:15.0

用到了二分图的一些性质, 最大匹配数=最小点覆盖

 貌似在白书上有讲

还不是很懂, 自己看着别人的博客用网络流写了一遍

反正以后学白书应该会系统学二分图的,紫书上没讲深。

目前就这样吧。

#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;
}