pku 2446(二分匹配)

题意就是一个棋盘,有N个hole,问能否用1*2的矩形覆盖所有的非hole点

一个小陷阱就是输入的hole坐标的行和列是反的

 

对每一个点,和它的上下左右的点比较,如果没有越界且不是hole点,则在2分图中连一条边,最后求二分匹配,若最大匹配数等于

棋盘点的总数减去hole点则有解,否则无解

 19xx  ms险过

 

#include <iostream> using namespace std; const int MAXN=35; bool map[MAXN][MAXN]; bool used[MAXN*MAXN+5],g[MAXN*MAXN+5][MAXN*MAXN+5]; int link[MAXN*MAXN+5],m,n,row,col; bool check(int t) //找增广路的递归过程 { for(int i=1;i<=m;i++) { if(!used[i]&&g[t][i]) { used[i]=true; if(!link[i]||check(link[i])) //这个就是判断Y集合里第i个点是否被匹配,是的话就递归去到跟它匹配的那个点。直到!link[i]为true为止 { link[i]=t; return true; } } } return false; } int Max() //这是主过程,从第i个开始寻找增广路,找到了匹配数+1,没找到就跳过 { int ans=0; for(int i=1;i<=n;i++) { memset(used,false,sizeof(used)); if(check(i)) ans++; } return ans; } void create_G() //构图 { int tag_s,tag_t; memset(link,0,sizeof(link)); for(int i=1;i<=row;++i) for(int j=1;j<=col;++j) { if(map[i][j]) continue; //如果是 hole过滤掉 tag_s=(i-1)*col+j; if(i>1 && !map[i-1][j]) { tag_t=(i-2)*col+j; g[tag_s][tag_t]=true; } if(i<row && !map[i+1][j]) { tag_t=i*col+j; g[tag_s][tag_t]=true; } if(j>1 && !map[i][j-1]) { tag_t=(i-1)*col+j-1; g[tag_s][tag_t]=true; } if(j<col && !map[i][j+1]) { tag_t=(i-1)*col+j+1; g[tag_s][tag_t]=true; } } } int main() { int num,a,b,sum; cin>>row>>col>>num; memset(map,false,sizeof(map)); memset(g,false,sizeof(g)); m=row*col; n=m; sum=m-num; for(int i=0;i<num;++i) { cin>>a>>b; map[b][a]=true; //小陷阱,列与行是反的 } create_G(); if(sum==Max()) cout<<"YES"<<endl; else cout<<"NO"<<endl; system("pause"); return 0; }

你可能感兴趣的:(pku 2446(二分匹配))