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;
}
浙公网安备 33010602011771号