题目:http://poj.org/problem?id=2446
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 15250 | Accepted: 4751 |
Description
Input
Output
Sample Input
4 3 2 2 1 3 3
Sample Output
YES
Hint
分析:一眼能看出这是二分匹配吗?所以我觉得这很经典(当然我也是听了别人的思路才懂的)。一张卡片是1*2的规模,所以一个格子就有上下左右四种可能的相邻的格子与他组合成卡片(没有hole),这就是匹配的雏形,于是用邻接表把所有格子的各种匹配情况都表示出来,最后用匈牙利最大匹配求出结果再与总的格子数,holes数做关系比较就能得到最终的判断。#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int N=2000; bool bmap[N][N],bmask[N],tag[35][35]; int nx,ny,cx[N],cy[N]; int find(int u){ for(int j=1;j<=ny;j++){ if(bmap[u][j]&&!bmask[j]){ bmask[j]=1; if(cy[j]==-1||find(cy[j])){ cy[j]=u; cx[u]=j; return 1; } } } return 0; } int maxmatch(){ int res=0; memset(cx,-1,sizeof(cx)); memset(cy,-1,sizeof(cy)); for(int i=1;i<=nx;i++){ if(cx[i]==-1){ for(int j=1;j<=ny;j++) bmask[j]=0; res+=find(i); } } return res; } int dir[4][2]={{0,-1},{0,1},{-1,0},{1,0}}; int main() { //freopen("cin.txt","r",stdin); int m,n,k; while(cin>>m>>n>>k){ int a,b; nx=ny=n*m; memset(tag,0,sizeof(tag)); memset(bmap,0,sizeof(bmap)); for(int i=0;i<k;i++){ scanf("%d%d",&b,&a); tag[a][b]=1; } for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ if(tag[i][j]==1) continue; int x,y; for(int k=0;k<4;k++){ x=i+dir[k][0]; y=j+dir[k][1]; if(x<=m&&x>=1&&y<=n&&y>=1&&tag[x][y]==0){ a=(i-1)*n+j; b=(x-1)*n+y; bmap[a][b]=1; } } } } int res=maxmatch(); //cout<<res<<endl; if(res==m*n-k) puts("YES"); else puts("NO"); } return 0; }