poj 2226 Muddy Fields 最小点覆盖
转换成求最小点覆盖数
构图方式如下:横行的连续*方块作为X集合里的顶点,纵行的连续*方块作为Y集合的顶点,若两个方块相交,则用边把这两个顶点相连。然后求最小点覆盖数(求最大匹配),即为答案。
要注意构图后的顶点数。
#include <iostream> #include <cstring> using namespace std; const int N = 55; const int MAX = N*N; struct Xblock { int x; int sty, edy; }; struct Yblock { int y; int stx, edx; }; Xblock xblock[MAX]; Yblock yblock[MAX]; bool maze[MAX][MAX]; char map[N][N]; bool isvisit[MAX]; int match[MAX]; int cnt_x, cnt_y; int row, col; void build_graph() { cnt_x = 0; cnt_y = 0; for (int i = 0; i < row; i++) for (int j = 0; j < col; j++) { if (map[i][j] == '*') { xblock[cnt_x].x = i; xblock[cnt_x].sty = j; while (j < col && map[i][j] == '*') { xblock[cnt_x].edy = j; j++; } cnt_x++; } } for (int j = 0; j < col; j++) for (int i = 0; i < row; i++) { if (map[i][j] == '*') { yblock[cnt_y].y = j; yblock[cnt_y].stx = i; while (i < row && map[i][j] == '*') { yblock[cnt_y].edx = i; i++; } cnt_y++; } } memset(maze, false, sizeof(maze)); for (int i = 0; i < cnt_x; i++) for (int j = 0; j < cnt_y; j++) if (xblock[i].x >= yblock[j].stx && xblock[i].x <= yblock[j].edx && yblock[j].y >= xblock[i].sty && yblock[j].y <= xblock[i].edy) maze[i][j] = true; } bool find(int u) { for (int i = 0; i < cnt_y; i++) { if (maze[u][i] && !isvisit[i]) { isvisit[i] = true; if (match[i] == -1 || find(match[i])) { match[i] = u; return true; } } } return false; } int main() { cin >> row >> col; for (int i = 0; i < row; i++) for (int j = 0; j < col; j++) cin >> map[i][j]; build_graph(); memset(match, -1, sizeof(match)); int ans = 0; for (int i = 0; i < cnt_x; i++) { memset(isvisit, false, sizeof(isvisit)); if (find(i)) ans++; } cout << ans << endl; return 0; }