题目:http://poj.org/problem?id=2446
思路:对相邻的格子染上不同的颜色,并对没障碍物的相邻格子之间连边,建立一个二分图,求是否每个无障碍格子都能被匹配。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 #define M N*N 7 #define N 2020 8 struct edge{ 9 int to,next; 10 }e[M]; 11 int pre[N],b[N],mat[N],visit[N]; 12 int cnt; 13 void add(int a,int b) 14 { 15 e[cnt].to=b; 16 e[cnt].next=pre[a]; 17 pre[a]=cnt++; 18 } 19 int dfs(int u) 20 { 21 for(int edg=pre[u];edg!=0;edg=e[edg].next) 22 { 23 int v=e[edg].to; 24 if(visit[v])continue; 25 visit[v]=1; 26 if(mat[v]==-1||dfs(mat[v])) 27 { 28 mat[v]=u; 29 return true; 30 } 31 } 32 return false; 33 } 34 int n,m; 35 int dir[4][2]={-1,0,0,1,1,0,0,-1}; 36 bool in(int x,int y) 37 { 38 if(x>=0&&x<n&&y>=0&&y<m)return true; 39 else return false; 40 } 41 int main() 42 { 43 int k; 44 while(scanf("%d%d%d",&n,&m,&k)!=EOF) 45 { 46 memset(b,-1,sizeof(b)); 47 memset(pre,0,sizeof(pre)); 48 cnt=1; 49 for(int i=1;i<=k;i++) 50 { 51 int a,c; 52 scanf("%d%d",&a,&c); 53 b[(c-1)*m+a-1]=0; 54 } 55 int cn=0; 56 for(int i=0;i<n*m;i++) 57 { 58 int x=i/m; 59 int y=i%m; 60 if((x+y)%2)continue; 61 if(b[i]==-1)cn++; 62 for(int j=0;j<4;j++) 63 { 64 int x0=x+dir[j][0]; 65 int y0=y+dir[j][1]; 66 if(in(x0,y0)) 67 { 68 if(b[i]==-1&&b[x0*m+y0]!=0)add(i,x0*m+y0); 69 } 70 } 71 } 72 if(cn!=n*m-k-cn){cout<<"NO"<<endl;continue;} 73 int flag=0; 74 memset(mat,-1,sizeof(mat)); 75 for(int i=0;i<n*m;i++) 76 { 77 memset(visit,0,sizeof(visit)); 78 if((i%m+i/m)%2==0&&b[i]!=0) 79 { 80 if(!dfs(i)){flag=1;break;} 81 } 82 } 83 if(flag)cout<<"NO"<<endl; 84 else cout<<"YES"<<endl; 85 } 86 return 0; 87 }