您的位置:首页 > 其它

POJ 2446 Chessboard(二分匹配-hungary)

2015-12-31 13:20 399 查看
Description

一个n*m的棋盘,棋盘上有k个洞,问能否用1*2的纸片恰好覆盖所有不是洞的格子,所谓恰好就是所有不是洞格子都被覆盖且只被覆盖一次

Input

第一行三个整数n,m和k分别表示棋盘行列数以及洞的数量,之后k行每行两个整数i和j表示这个洞位于棋盘第i行第j列

Output

如果恰能用1*2的纸片覆盖所有不是洞的格子则输出YES,否则输出NO

Sample Input

4 3 2

2 1

3 3

Sample Output

YES

Solution

二分匹配,将每一个不是洞的格子看作一个点,显然一个1*2纸片覆盖的两个格子行列和的奇偶性不同,所以可以将此题转化为两排点的二分匹配,一排点行列和为奇,另一排行列和为偶,对于每一个不是洞且行列和为奇的格子,将其与其上下左右四个格子中不是洞的格子建边,最后看最大匹配数的二倍是否等于n*m-k,是则说明可行,否则不行

Code

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define maxn 1111
int uN,vN;//u,v数目
int g[maxn][maxn];//编号是0~n-1的
int linker[maxn];
bool used[maxn];
bool dfs(int u)
{
int v;
for(v=0;v<vN;v++)
if(g[u][v]&&!used[v])
{
used[v]=true;
if(linker[v]==-1||dfs(linker[v]))
{
linker[v]=u;
return true;
}
}
return false;
}
int hungary()
{
int res=0;
int u;
memset(linker,-1,sizeof(linker));
for(u=0;u<uN;u++)
{
memset(used,0,sizeof(used));
if(dfs(u))  res++;
}
return res;
}
int main()
{
int n,m,k,Map[33][33];
while(~scanf("%d%d%d",&n,&m,&k))
{
memset(g,0,sizeof(g));
uN=vN=0;
memset(Map,0,sizeof(Map));
for(int i=1;i<=k;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Map[y][x]=-1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(Map[i][j]==-1)continue;
if((i+j)%2)Map[i][j]=uN++;
else Map[i][j]=vN++;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(Map[i][j]!=-1&&((i+j)%2))
{
if(i-1>=1&&Map[i-1][j]!=-1)g[Map[i][j]][Map[i-1][j]]=1;
if(i+1<=n&&Map[i+1][j]!=-1)g[Map[i][j]][Map[i+1][j]]=1;
if(j-1>=1&&Map[i][j-1]!=-1)g[Map[i][j]][Map[i][j-1]]=1;
if(j+1<=m&&Map[i][j+1]!=-1)g[Map[i][j]][Map[i][j+1]]=1;
}
if(hungary()*2==m*n-k)printf("YES\n");
else printf("NO\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: