[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 }

 

你可能感兴趣的:(poj)