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.

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;
}