poj 2446二分图匹配

题意:爱丽丝和波波经常玩棋盘游戏,爱丽丽画出一个m*n的棋盘,让波波在棋盘中填充1*2大小的矩形条,而且爱丽丝不想这么轻易让波波赢,她将m*n的棋盘中挖掉k个方格。

1.每个矩形条必需覆盖矩阵中相临两个方格
2.矩形条不能覆盖挖去的方格。
对于给定的m*n的且某些方格被挖去的矩阵,问用某种覆盖方法能否将除挖掉的方格外所有方格全部覆盖,若能,输出YES,否则输出NO。

思路:
矩形条每次覆盖相临两个方格。那么对两个任意方格(看作结点),如果它们分属两个不同的集合的话,那么它们之间存在边的情况只有它们是相临的方格的时候。这样一来,我们可以将矩阵中所有元素分成两个点集,相临点间存在边的关系。那么如何分这两个集合呢, 发现一个方块的行标和列标之和若为奇数则它周围的四个方块的行标和列标之和必为偶数;一个方块的行标和列标之和若为偶数则它周围的四个方块的行标和列标之和必为奇数,奇数一个集合,偶数一个集合,只连左边和上边。这样一个二分图就建完了。

  1 // File Name: 2446.cpp
  2 // Author: Missa
  3 // Created Time: 2013/4/3 星期三 13:56:33
  4 
  5 #include<iostream>
  6 #include<cstdio>
  7 #include<cstring>
  8 #include<algorithm>
  9 #include<cmath>
 10 #include<queue>
 11 #include<stack>
 12 #include<string>
 13 #include<vector>
 14 #include<cstdlib>
 15 #include<map>
 16 #include<set>
 17 using namespace std;
 18 #define CL(x,v) memset(x,v,sizeof(x));
 19 #define R(i,st,en) for(int i=st;i<en;++i)
 20 #define LL long long
 21 #define inf 0x3f3f3f3f
 22 
 23 const int maxn = 33;
 24 int n,m,k;
 25 int in[maxn][maxn];
 26 int g[maxn * maxn][maxn * maxn];
 27 int nx,ny;
 28 bool vis[maxn * maxn];
 29 int link[maxn * maxn];
 30 bool dfs(int x)
 31 {
 32     R(y, 1, ny+1)
 33     {
 34         if(!vis[y] && g[x][y])
 35         {
 36             vis[y] =1;
 37             if(link[y] == -1 || dfs(link[y]))
 38             {
 39                 link[y] = x;
 40                 return 1;
 41             }
 42         }
 43     }
 44     return false;
 45 }
 46 int maxmatch()
 47 {
 48     int ans = 0;
 49     CL(link,-1);
 50     R(x, 1, nx+1)
 51     {
 52         CL(vis, 0);
 53         if(dfs(x)) ans++;
 54     }
 55     return ans;
 56 }
 57 void init()
 58 {
 59     nx = ny = 0;
 60     CL(g, 0);
 61     for (int i = 1; i <= n; ++i)
 62     {
 63         for (int j = 1; j <= m; ++j)
 64         {
 65             if (in[i][j] == -1) continue;
 66             if ((i + j) & 1)
 67             {
 68                 in[i][j] = ++nx;
 69                 if (i - 1 >= 1 && in[i-1][j] != -1)
 70                     g[nx][in[i-1][j]] = 1;
 71                 if (j - 1 >= 1 && in[i][j-1] != -1)
 72                     g[nx][in[i][j-1]] = 1;
 73             }
 74             else
 75             {
 76                 in[i][j] = ++ny;
 77                 if (i - 1 >= 1 && in[i-1][j] != -1)
 78                     g[in[i-1][j]][ny] = 1;
 79                 if (j - 1 >= 1 && in[i][j-1] != -1)
 80                     g[in[i][j-1]][ny] = 1;
 81             }
 82         }
 83     }
 84 }
 85 int main()
 86 {
 87     while(~scanf("%d%d%d",&n, &m, &k))
 88     {
 89         CL(in, 0);
 90         R(i, 0, k)
 91         {
 92             int x, y;
 93             scanf("%d%d", &y, &x);
 94             in[x][y] = -1;
 95         }
 96         if((n * m - k) & 1)
 97         {
 98             printf("NO\n");
 99             continue;
100         }
101         init();
102         if(maxmatch() * 2 == (n * m - k))
103             printf("YES\n");
104         else
105             printf("NO\n");
106     }
107     return 0;
108 }
原文地址:https://www.cnblogs.com/Missa/p/2997960.html