【二分图最大匹配】poj2446
Chessboard
Description
Alice and Bob often play games on chessboard. One day, Alice draws a board with size M * N. She wants Bob to use a lot of cards with size 1 * 2 to cover the board. However, she thinks it too easy to bob, so she makes some holes on the board (as shown in the figure below).
We call a grid, which doesn’t contain a hole, a normal grid. Bob has to follow the rules below:
1. Any normal grid should be covered with exactly one card.
2. One card should cover exactly 2 normal adjacent grids.
Some examples are given in the figures below:
A VALID solution.
An invalid solution, because the hole of red color is covered with a card.
An invalid solution, because there exists a grid, which is not covered.
Your task is to help Bob to decide whether or not the chessboard can be covered according to the rules above.
We call a grid, which doesn’t contain a hole, a normal grid. Bob has to follow the rules below:
1. Any normal grid should be covered with exactly one card.
2. One card should cover exactly 2 normal adjacent grids.
Some examples are given in the figures below:
A VALID solution.
An invalid solution, because the hole of red color is covered with a card.
An invalid solution, because there exists a grid, which is not covered.
Your task is to help Bob to decide whether or not the chessboard can be covered according to the rules above.
Input
There are 3 integers in the first line: m, n, k (0 < m, n <= 32, 0 <= K < m * n), the number of rows, column and holes. In the next k lines, there is a pair of integers (x, y) in each line, which represents a hole in the y-th row, the x-th column.
Output
If the board can be covered, output "YES". Otherwise, output "NO".
Sample Input
4 3 2 2 1 3 3
Sample Output
YES
Hint
A possible solution for the sample input.
大意:一个M*N的棋盘上有k个洞,问能否用1*2的骨牌将棋盘没有洞的点全部覆盖
方法:将棋盘黑白染色,然后如果没有洞就与相邻的没有洞的点连上边,求最大匹配,如果最大匹配数*2等于没有洞的点就可以覆盖住
(差点连黑白染色都不会了, 太渣了!%>_<%)
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const long movex[4] = {0, 0, 1, -1};
const long movey[4] = {-1, 1, 0, 0};
const long N = 10010, M = 40010;
long edge[N][5];
long l[N];
bool a[101][101];
bool b[N];
long n, m, k, nn;
bool find(long x)
{
for(long i = 1; i <= edge[x][0]; i++)
{
long j= edge[x][i];
if (!b[j])
{
b[j] = true;
if((l[j] == 0)||(find(l[j])))
{
l[j] = x;
return true;
}
}
}
return false;
}
void init()
{
memset(a, true, sizeof(a));
for (long i = 1; i <= k; i++)
{
long x, y;
scanf("%ld%ld", &x, &y);
a[y][x] = false;
}
memset(edge, 0, sizeof(edge));
for (long i = 1; i <= n; i++)
for (long j = 1; j <= m ; j++)
{
if (a[i][j])
{
if ((i + j) % 2 == 0)
{
for (long k = 0; k < 4; k++)
{
long x = i + movex[k];
long y = j + movey[k];
if ((x <= 0)||(x > n)) continue;
if ((y <= 0)||(y > m)) continue;
if (a[x][y])
{
long q1 = (i - 1) * m + j;
long q2 = (x - 1) * m + y;
edge[q1][0]++;
edge[q1][edge[q1][0]] = q2;
}
}
}
}
}
}
int main()
{
freopen("poj2446.in", "r", stdin);
while(scanf("%ld%ld%ld", &n, &m, &k)!= EOF)
{
init();
long re = 0;
memset(l, 0, sizeof(l));
for(long i = 1; i <= n; i++)
for(long j = 1; j <= m; j++)
{
if ((i + j) % 2 == 0)
{
long tmp = (i - 1) * m + j;
memset(b, 0, sizeof(b));
if ( find(tmp))
{
re++;
}
}
}
if (re * 2 + k == n * m) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}