题意:给定一个M*N的长方形,要求用1*2的小长方形填充,但是其中有些小方格被挖了洞,现在问是否可以将所有的空格填充完。
想法:
简单的而二分图的模板题。
建图方法好像不唯一。
我是把每个空格子当成一个点。
然后对于每个格子如果可以往上、下、左、右去找可以建立的边。
然后求最大匹配,如果最大匹配数刚好等于空格子数,输出YES,否则NO。
![](https://i-blog.csdnimg.cn/blog_migrate/4510260588b39cd59a2e5a79e9306673.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/fbad19a66a677c926c13acc9b3c05d88.jpeg)
A VALID solution.
![](https://i-blog.csdnimg.cn/blog_migrate/d48c0b8bae885a1505438acbac2989f3.jpeg)
An invalid solution, because the hole of red color is covered with a card.
![](https://i-blog.csdnimg.cn/blog_migrate/cbda8a0f78ee86f8b8399405d75c16a0.jpeg)
An invalid solution, because there exists a grid, which is not covered.
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=1060;
int n1,n2;
int _map[N][N];
bool vis[N];
int llink[N];
int find(int x) {
int i;
for(i=0; i<n2; i++) {
if(_map[x][i]&&!vis[i]) {
vis[i]=true;
if(llink[i]==-1||find(llink[i])) {
llink[i]=x;
return true;
}
}
}
return false;
}
int mach() {
int ans=0;
memset(llink,-1,sizeof(llink));
for(int i=0; i<n1; i++) {
memset(vis,false,sizeof(vis));
if(find(i)) {
ans++;
}
}
return ans;
}
int main() {
int k;
int x,y;
int n,m;
bool tmp_map[50][50];
int num[50][50];
while(~scanf("%d%d%d",&m,&n,&k)) {
memset(_map,0,sizeof(_map));
memset(tmp_map,false,sizeof(tmp_map));
for(int i=0; i<k; i++) {
scanf("%d%d",&x,&y);
x--;
y--;
tmp_map[y][x]=true;
}
int tol=0;
for(int i=0; i<m; i++) {
for(int j=0; j<n; j++) {
if(tmp_map[i][j]==false) {
num[i][j]=tol++;
}
}
}
n1=n2=tol;
for(int i=0; i<m; i++) {
for(int j=0; j<n; j++) {
if(!tmp_map[i][j]) {
int u=num[i][j];
if(i>0&&!tmp_map[i-1][j]) {
_map[u][num[i-1][j]]=1;
}
if(j>0&&!tmp_map[i][j-1]) {
_map[u][num[i][j-1]]=1;
}
if(i<m-1&&!tmp_map[i+1][j]) {
_map[u][num[i+1][j]]=1;
}
if(j<n-1&&!tmp_map[i][j+1]) {
_map[u][num[i][j+1]]=1;
}
}
}
}
//printf("%d %d\n",mach(),tol);
if(mach()==tol){
printf("YES\n");
}else{
printf("NO\n");
}
}
return 0;
}