zoj 1654 Place the Robots 最大二分匹配
转换成最大匹配。
每个横向的'o’和'#’块(必须包含'o’)作为X集合一个顶点,每个纵向的'o’和'#’块(必须包含'o’)作为Y集合一个顶点
当横向块和纵向块的交点的'o’时,二分图该两个顶点有边相连接。
这题因为下标不小心打错了,调了很久才ac,纳闷。
#include <iostream>
#include <cstring>
using namespace std;
const int N = 55;
const int MAX = N*N;
struct hori_block
{
int row;
int col_left, col_right;
};
struct ver_block
{
int col;
int row_up, row_dow;
};
hori_block X[MAX];
ver_block Y[MAX];
char map[N][N];
bool maze[MAX][MAX];
int match[MAX];
bool isvisit[MAX];
int row, col;
int cnt_x, cnt_y;
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] == 'o')
{
X[cnt_x].row = i;
for (int k = j; k >= 0; k--)
if (map[i][k] != '#')
X[cnt_x].col_left = k;
else
break;
while (j < col && map[i][j] != '#')
{
X[cnt_x].col_right = j;
j++;
}
cnt_x++;
}
}
for (int j = 0; j < col; j++)
for (int i = 0; i < row; i++)
{
if (map[i][j] == 'o')
{
Y[cnt_y].col = j;
for (int k = i; k >= 0; k--)
if (map[k][j] != '#')
Y[cnt_y].row_up = k;
else
break;
while (i < row && map[i][j] != '#')
{
Y[cnt_y].row_dow = 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 (X[i].row >= Y[j].row_up && X[i].row <= Y[j].row_dow
&& Y[j].col >= X[i].col_left && Y[j].col <= X[i].col_right
&& map[ X[i].row ][ Y[j].col ] == 'o')
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 max_match()
{
int ans = 0;
memset(match, -1, sizeof(match));
for (int i = 0; i < cnt_x; i++)
{
memset(isvisit, false, sizeof(isvisit));
if (find(i))
ans++;
}
return ans;
}
int main()
{
int cases;
cin >> cases;
for (int k = 1; k <= cases; k++)
{
cin >> row >> col;
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
cin >> map[i][j];
build_graph();
cout << "Case :" << k << endl;
cout << max_match() << endl;
}
return 0;
}
浙公网安备 33010602011771号