POJ 2446 Chessboard 匹配/最小路径覆盖
http://poj.org/problem?id=2446
跟 poj 3020差不多
以前做过一个最小路径覆盖的题,读完这个题就想到了最小路径覆盖。很多大神用的完全匹配,有一点值得学习,就是根据i+j的奇偶性,把点分成两个集合,这样也可以?!
最小路径覆盖的代码(为什么我的运行时间那么长??):
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[35][35],link[1500],map[1500][1500];
bool vs[1500];
int n,m,N,M;
bool dfs(int x)
{
for(int i=1;i<=M;i++)
{
if(map[x][i]&&!vs[i])
{
vs[i]=1;
if(!link[i]||dfs(link[i]))
{
link[i]=x;
return 1;
}
}
}
return 0;
}
int MaxMatch()
{
int i,cnt=0;
memset(link,0,sizeof(link));
for(i=1;i<=N;i++)
{
memset(vs,0,sizeof(vs));
if(dfs(i))cnt++;
}
return cnt;
}
int main()
{
int i,j,k,h;
while(~scanf("%d%d%d",&n,&m,&k))
{
memset(a,-1,sizeof(a));
for(h=1;h<=k;h++)
{
scanf("%d%d",&i,&j);
a[j][i]=0;//有洞
}
if((n*m-k)%2!=0){printf("NO\n");continue;}
N=0,M=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if(a[i][j]==-1)
{
if((i+j)%2==1)
a[i][j]=++N; //没有hole的
else a[i][j]=++M;
}
}
memset(map,0,sizeof(map));
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if(a[i][j]<1||(i+j)%2==0)continue;
if(a[i-1][j]>=1)
map[a[i][j]][a[i-1][j]]=1;
if(a[i+1][j]>=1)
map[a[i][j]][a[i+1][j]]=1;
if(a[i][j-1]>=1)
map[a[i][j]][a[i][j-1]]=1;
if(a[i][j+1]>=1)
map[a[i][j]][a[i][j+1]]=1;
}
int ans=MaxMatch();//最大匹配
if(ans==(n*m-k)/2)printf("YES\n");
else printf("NO\n");
}
return 0;
}

浙公网安备 33010602011771号