二分图找最大点覆盖集,看是否能覆盖图中的所有点
难度不高。。但是对我这种星际玩家来说简直是噩梦。。(被它的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; }