POJ 2446 Chessboard二分图匹配

来源:互联网 发布:linux 查看文件多少行 编辑:程序博客网 时间:2024/06/10 17:35

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 22 13 3

Sample Output

YES

Hint


A possible solution for the sample input.


大意:一个棋盘,有k个点被标记特殊点,现在要求用1*2的小纸条覆盖整个棋盘,除特殊点外,且一个点不能被多个纸条覆盖到。问是否能办到。棋盘大小m*n(m,n<32,k<m*n)
分析:刚看这道题绞尽脑汁,因为是棋盘覆盖的题所以总以为会是分治或者是搜索什么的,结果联系了下最近学的二分图,发现了这么个情况:纸条大小1*2,也就是每个纸条只能覆盖相邻的两个点,而每个点最多被覆盖一次。意思是说每个点能跟哪几个点共用一个纸条(即匹配)是确定的,这样的话二分图的模型就出来了。
     怎么二分呢?我们把棋盘按照国际象棋的棋盘那样“涂色”,也就是一个黑点必匹配一个白点。我们给没个黑白点编号,且每个点和周围的最多四个点建一条边,这样二分图的模型就构造好了。最多有m*n/2个黑或白点,匈牙利算法不会超时。
    做匈牙利算法算出最大匹配ans,判断ans*2是否==m*n-k,如果等,说明每个点都被覆盖了,可解。不等,则不存在解。
代码如下:
#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>#include<string>#define MAXN 34using namespace std;int N,K,M,match[MAXN*MAXN],nb,nw,ans;bool map[MAXN*MAXN][MAXN*MAXN],use[MAXN*MAXN];int id[MAXN][MAXN],co[MAXN][MAXN];int dx[4]={0,0,1,-1};int dy[4]={1,-1,0,0};bool DFS(int u){for(int i=1;i<=nw;i++)if(!use[i]&&map[u][i]){use[i]=1;if(match[i]==-1||DFS(match[i])){match[i]=u;return 1;}}return 0;}int main(){while(scanf("%d%d%d",&M,&N,&K)!=EOF){memset(co,-1,sizeof(co));memset(map,0,sizeof(map));memset(id,0,sizeof(id));memset(match,-1,sizeof(match));nb=nw=ans=0;for(int i=1;i<=K;i++){int xx,yy;scanf("%d%d",&xx,&yy);co[xx][yy]=0;}for(int i=1;i<=N;i++)for(int j=1;j<=M;j++){if(co[i][j]==0) continue;if((i%2==1&&j%2==1)||(i%2==0&&j%2==0)){co[i][j]=1;//blackid[i][j]=++nb;}else{co[i][j]=2;//whiteid[i][j]=++nw;}}for(int i=1;i<=N;i++)for(int j=1;j<=M;j++){if(co[i][j]==0) continue;for(int k=0;k<4;k++){int tx=i+dx[k],ty=j+dy[k];if(tx>=1&&tx<=N&&ty>=1&&ty<=M&&co[tx][ty]!=0){if(co[i][j]==1) map[id[i][j]][id[tx][ty]]=1;if(co[i][j]==2) map[id[tx][ty]][id[i][j]]=1;}}}for(int i=1;i<=nb;i++){memset(use,0,sizeof(use));if(DFS(i)) ans++;}if(ans*2==M*N-K) printf("YES\n");else printf("NO\n");}return 0;}


原创粉丝点击