[POJ] 2446 Chessboard(二分图最大匹配)

题目地址:http://poj.org/problem?id=2446

本题建图是关键。因为卡片都是1*2,所以若点V被某个1*2卡片覆盖,则周围包含V的其它1*2区域都不成立。所以想到只要把V点划分在X集合,周围点在Y集合,V向周围点分别连边,就变成了二分图匹配问题,区分点V与周围点可以用横纵坐标之和的奇偶性。若棋盘上除障碍外都能被1*2卡片覆盖,则最大匹配数ans=(棋盘所有点数n*m-障碍数k)/2。本题在进行之前还有一个小优化,如果n*m-k是奇数,显而易见是不成立的,所以直接返回NO。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<string.h>
  4 #include<algorithm>
  5 #include<math.h>
  6 #include<stdbool.h>
  7 #include<time.h>
  8 #include<stdlib.h>
  9 #include<set>
 10 #include<map>
 11 #include<stack>
 12 #include<queue>
 13 #include<vector>
 14 using namespace std;
 15 #define clr(x,y)    memset(x,y,sizeof(x))
 16 #define sqr(x)      ((x)*(x))
 17 #define rep(i,a,b)  for(int i=(a);i<=(b);i++)
 18 #define LL          long long
 19 #define INF         0x3f3f3f3f
 20 #define A           first
 21 #define B           second
 22 #define PI          3.14159265358979323
 23 const int N=2000+11;
 24 const int dx[4]={0,0,1,-1};
 25 const int dy[4]={1,-1,0,0};
 26 int n,m,k1,k,k2,f[N],g[N][N],link[N],flag[N][N],a[N],b[N];
 27 
 28 void init()
 29 {
 30     clr(f,0);
 31     clr(g,0);
 32     clr(flag,0);
 33     clr(a,0);
 34     clr(b,0);
 35     clr(link,-1);
 36     k1=0;
 37     k2=0;
 38 }
 39 
 40 bool find(int x)
 41 {
 42     for(int i=0;i<k2;i++) {
 43         if(!f[b[i]] && g[x][b[i]]) {
 44             f[b[i]]=1;
 45             if(link[b[i]]==-1 || find(link[b[i]])) {
 46                 link[b[i]]=x;
 47                 return true;
 48             }
 49         }
 50     }
 51     
 52     return false;
 53 }
 54 
 55 int hungary()
 56 {
 57     int ans=0;
 58     for(int i=0;i<k1;i++) {
 59         clr(f,0);
 60         if(find(a[i])) ans++;
 61     }
 62     return ans;
 63 }
 64 
 65 int main()
 66 {
 67     int u,v,x,y;
 68     
 69     init(); 
 70     scanf("%d%d%d",&m,&n,&k);
 71     if((m*n-k)&1) {
 72         printf("NO\n");
 73         return 0;
 74     }
 75     for(int i=1;i<=m;i++) {
 76         for(int j=1;j<=n;j++) 
 77         flag[i][j]=1;
 78     }
 79     for(int i=1;i<=k;i++) {
 80         scanf("%d%d",&y,&x);
 81         flag[x][y]=0;
 82     }
 83 
 84     for(int i=1;i<=m;i++) {
 85         for(int j=1;j<=n;j++) {
 86             
 87             int p=(i-1)*n+j;
 88             if((i+j)&1) {
 89                 if(flag[i][j]) a[k1++]=p;
 90             }  else {
 91                 if(flag[i][j]) b[k2++]=p;
 92             }   
 93         }
 94     }
 95     
 96     for(int i=1;i<=m;i++) {
 97         for(int j=1;j<=n;j++) {
 98             if(flag[i][j])
 99             for(int k=0;k<4;k++) {
100                 int nx=i+dx[k];
101                 int ny=j+dy[k];
102                 if(flag[nx][ny]) {
103                     g[(i-1)*n+j][(nx-1)*n+ny]=1;
104                 }
105             }
106         }
107     }
108    
109    if(2*hungary()+k==n*m) printf("YES\n");
110    else  printf("NO\n");
111     
112     return 0;
113 }

 

posted @ 2015-03-30 17:03  SXISZERO  阅读(271)  评论(0编辑  收藏  举报