标签:二分匹配
4 4 6 1 1 1 4 2 2 4 1 4 2 4 4 4 3 4 4 2 3 2 2 2 3 1 0 0
4 (1,2)--(1,3) (2,1)--(3,1) (2,3)--(3,3) (2,4)--(3,4) 3 (1,1)--(2,1) (1,2)--(1,3) (2,3)--(3,3)
二分匹配,建边的依据是枚举所有可行的点,然后枚举周围四个方向;输出方案依据mark数组
#include <map> #include <set> #include <list> #include <queue> #include <stack> #include <vector> #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 10010; struct node { int to; int next; }edge[4 * maxn]; int vis[maxn]; int head[maxn]; int mark[maxn]; bool used[maxn]; bool mat[110][110]; int cnt[110][110]; int tot; int n, m; int index; void addedge(int from, int to) { edge[tot].to = to; edge[tot].next = head[from]; head[from] = tot++; } bool dfs(int x) { for (int i = head[x]; i != -1; i = edge[i].next) { if (!used[edge[i].to]) { used[edge[i].to] = 1; if (mark[edge[i].to] == -1 || dfs(mark[edge[i].to])) { mark[edge[i].to] = x; return true; } } } return false; } int hungary() { memset(mark, -1, sizeof(mark)); int ans = 0; for (int i = 0; i < index; i++) { memset(used, 0, sizeof(used)); if (dfs(i)) ans++; } return ans; } int main() { int k; while (~scanf("%d%d", &n, &m)) { if (!n && !m) { break; } scanf("%d", &k); map<int, int>qu; qu.clear(); memset(head, -1, sizeof(head)); memset(mat, false, sizeof(mat)); memset(vis, -1, sizeof(vis)); tot=0; int x, y; for (int i = 0; i < k; i++) { scanf("%d%d", &x, &y); x--; y--; mat[x][y] = true; } index = 0; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) if (!mat[i][j]) { cnt[i][j] = index++; qu[index - 1] = i * m + j; } for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) { if (!mat[i][j]) { if (i > 0 && !mat[i - 1][j]) addedge(cnt[i][j], cnt[i - 1][j]); if (i < n-1 && !mat[i + 1][j]) addedge(cnt[i][j], cnt[i + 1][j]); if (j > 0 && !mat[i][j - 1]) addedge(cnt[i][j], cnt[i][j - 1]); if (j < m - 1 && !mat[i][j + 1]) addedge(cnt[i][j], cnt[i][j + 1]); } } int res = hungary(); printf("%d\n", res / 2); for (int i = 0; i < index; ++i) { if (mark[i] != -1) { int a = qu[i]; int b = qu[mark[i]]; int x1 = a / m + 1; int y1 = a % m + 1; int x2 = b / m + 1; int y2 = b % m + 1; if (vis[a] == -1 && vis[b] == -1) { printf("(%d,%d)--(%d,%d)\n", x1, y1, x2, y2); vis[a] = b; vis[b] = a; } } } printf("\n"); } return 0; }
hdu1507——Uncle Tom's Inherited Land*
标签:二分匹配
原文地址:http://blog.csdn.net/guard_mine/article/details/41315879