Chessboard
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 16624 | Accepted: 5171 |
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.
思路:状态压缩不行,32*32规模太大。所以这里考虑把图转换成二分图。
可是不能直接对每一个点建图,一个点可能会重复。
那么我们这里有一种巧妙的方式,把图进行黑白染色 (按照斜线染色),我们可以发现一个白点的上下左右一定是黑点,那么我们就可以把白点和黑点当成x和y集合,然后相邻的两个点连边
最后求所有的白点是否都能够成功匹配,比较一下ans*2+k==n*m(只有黑白数目相同并且全部匹配和才会满足这个条件)
注意:黑白染色形如
0 1 0
1 0 1
0 1 0
1 0 1
1是黑色,0是白色
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 2500
int dir[4][2]= {-1,0,1,0,0,-1,0,1};
int ma[N][N],d[N][N];
int line[N],vis[N];
struct Node
{
int x,y;
} p[N],q[N];
int can(int t,int m)
{
for(int i=1; i<m; i++)
{
if(!vis[i]&&ma[t][i]==1)
{
vis[i]=1;
if(line[i]==-1||can(line[i],m))
{
line[i]=t;
return 1;
}
}
}
return 0;
}
int main()
{
int n,m,k;
int x,y;
while(~scanf("%d %d %d",&n,&m,&k))
{
memset(ma,0,sizeof(ma));
memset(line,-1,sizeof(line));
memset(d,0,sizeof(d));
for(int i=1; i<=k; i++)
{
scanf("%d %d",&y,&x);
d[x][y]=-1;
}
int cn=1,cm=1;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
if(d[i][j]==-1) continue;
if(i&1)
{
if(j&1) p[cn].x=i,p[cn++].y=j;
else
{
d[i][j]=cm;
q[cm].x=i,q[cm++].y=j;
}
}
else
{
if(j&1)
{
d[i][j]=cm;
q[cm].x=i,q[cm++].y=j;
}
else p[cn].x=i,p[cn++].y=j;
}
}
}
for(int i=1; i<cn; i++)
{
x=p[i].x,y=p[i].y;
for(int j=0; j<4; j++)
{
int ux=x+dir[j][0],uy=y+dir[j][1];
if(ux<1||ux>n||uy<1||uy>m||d[ux][uy]==-1) continue;
int id=d[ux][uy];
ma[i][id]=1;
}
}
int ans=0;
for(int i=1; i<cn; i++)
{
memset(vis,0,sizeof(vis));
if(can(i,cm)) ans++;
else break;
}
if(ans*2+k==n*m) printf("YES\n");
else printf("NO\n");
}
return 0;
}