二分图找最大点覆盖集,看是否能覆盖图中的所有点
难度不高。。但是对我这种星际玩家来说简直是噩梦。。(被它的x、y的顺序坑惨了,而且还有YES和NO的大写让我WA了一下午QAQ)所以说好好读题才是正解吧。。。。
题目的时间和空间复杂度的限制都不卡人,随便水水就过去了(像我的n个for循环丢进去毫无压力)
#include<cstdio>
#include<cstring>
const int MAXN=2005;
int G[MAXN][MAXN];
bool b[MAXN];
int link[MAXN];
int m,n,k;
int cnt=0;
bool find(int x)
{
for(int i=1;i<=cnt;i++)
{
if(G[x][i]&&!b[i])
{
b[i]=1;
if(!link[i]||find(link[i]))
{
link[i]=x;
return 1;
}
}
}
return 0;
}
int ma[MAXN][MAXN];
int num[MAXN][MAXN];
int main()
{
while(std::scanf("%d%d%d",&m,&n,&k)!=EOF)
{
std::memset(G,0,sizeof(G));
std::memset(num,0,sizeof(num));
std::memset(ma,0,sizeof(ma));
std::memset(link,0,sizeof(link));
cnt=0;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
ma[i][j]=1;
}
}
for(int i=1;i<=k;i++)
{
int x,y;
std::scanf("%d%d",&x,&y);
ma[y][x]=0;//这里是真的太二了
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(ma[i][j])
num[i][j]=++cnt;
}
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(ma[i][j])
{
if(i-1>=1&&ma[i-1][j])
{
G[num[i][j]][num[i-1][j]]=1;
}
if(i+1<=m&&ma[i+1][j])
{
G[num[i][j]][num[i+1][j]]=1;
}
if(j-1>=1&&ma[i][j-1])
{
G[num[i][j]][num[i][j-1]]=1;
}
if(j+1<=n&&ma[i][j+1])
{
G[num[i][j]][num[i][j+1]]=1;
}
}
}
}
int result=0;
for(int i=1;i<=cnt;i++)
{
std::memset(b,0,sizeof(b));
if(find(i))
{
result++;
}
}
if(result==cnt)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
return 0;
}