题目大意:一个n*m的棋盘,某些格子不能用,问用1*2的骨牌能否完全覆盖这个棋盘,当然,骨牌不能有重叠
思路:显然黑白染色后,一个骨牌只能覆盖一个白色格子和一个黑色格子,然后我们间二染色建图,看能否有完美匹配即可TUT
#include <iostream>
#include <cstdio>
#include <string.h>
#define maxn 10000
using namespace std;
const int dx[10]={0,0,0,-1,1};
const int dy[10]={0,1,-1,0,0};
int head[maxn],next[maxn],point[maxn],now=0,map[maxn][maxn],id[maxn],match[maxn],h;
bool visit[maxn];
void add(int x,int y)
{
next[++now]=head[x];
head[x]=now;
point[now]=y;
}
int dfs(int k)
{
for(int i=head[k];i;i=next[i])if(!visit[point[i]])
{
int u=point[i];
visit[u]=1;
if(match[u]==-1 || dfs(match[u]))
{
match[u]=k;
return 1;
}
}
return 0;
}
int main()
{
int n,m,k,x,y,i;
scanf("%d%d%d",&n,&m,&k);
for(i=1;i<=k;i++)
{
scanf("%d%d",&y,&x);
map[x][y]=2;
}
int ans=k;
for(i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(map[i][j]!=2)map[i][j]=1;
}
}
int fi=1;
for(i=1;i<=n;i++)
{
fi^=1;
for(int j=fi+1;j<=m;j+=2)if(map[i][j]==1)
{
id[++h]=(i-1)*m+j;
// printf("%d %d\n",i,j);
for(int kk=1;kk<=4;kk++)
{
int xx=i+dx[kk],yy=j+dy[kk];
if(map[xx][yy]==1)
{
add((i-1)*m+j,(xx-1)*m+yy);
}
}
}
}
memset(match,-1,sizeof(match));
for(i=1;i<=h;i++)
{
memset(visit,0,sizeof(visit));
if(dfs(id[i]))ans+=2;
}
if(ans==n*m)printf("YES\n");else printf("NO\n");
return 0;
}