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

题目链接:http://poj.org/problem?id=2446

给你一个n*m的棋盘,其中有k个洞,现在有1*2大小的纸片,纸片不能覆盖洞,并且每个格子最多只能被覆盖一次。问你除了洞口之外这个棋盘是否能被纸片填满。

这个题目一眼很难看出是二分图匹配...

可以根据i和j性质可以看出,i+j为奇数的上下相邻的i'和j'一定是偶数,那么一个1*2的纸片的i+j一定是一个奇数一个偶数。所以我是建立一个二分图两个集合,将i+j为奇数的点与上下左右相邻的点连在一起,当然点不是洞。最后就用匈牙利算法求最大匹配数,然后就简单了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 using namespace std;
 6 const int N = 35* 35;
 7 vector <int> G[N];
 8 int match[N] , tx[] = {-1 , 0 , 1 , 0} , ty[] = {0 , 1 , 0 , -1} , n , m;
 9 bool vis[N] , map[35][35];
10 
11 bool check(int x , int y) {
12     if(!map[x][y] && x >= 0 && y >= 0 && x < n && y < m)
13         return true;
14     return false;
15 }
16 
17 bool dfs(int u) {
18     for(int i = 0 ; i < G[u].size() ; ++i) {
19         int v = G[u][i];
20         if(!vis[v]) {
21             vis[v] = true;
22             if(match[v] == -1 || dfs(match[v])) {
23                 match[v] = u;
24                 return true;
25             }
26         }
27     }
28     return false;
29 }
30 
31 int hungry() {
32     int res = 0;
33     for(int i = 0 ; i < n ; ++i) {
34         for(int j = 0 ; j < m ; ++j) {
35             if((i + j) % 2 && !map[i][j]) {
36                 memset(vis , false , sizeof(vis));
37                 if(dfs(i*m + j)) {
38                     res++;
39                 }
40             }
41         }
42     }
43     return res;
44 }
45 
46 int main()
47 {
48     int k , u , v;
49     while(cin >> n >> m >> k) {
50         memset(map , false , sizeof(map));
51         memset(match , -1 , sizeof(match));
52         for(int i = 0 ; i < n * m ; ++i) {
53             G[i].clear();
54         }
55         for(int i = 0 ; i < k ; ++i) {
56             cin >> u >> v;
57             map[--v][--u] = true;
58         }
59         for(int i = 0 ; i < n ; ++i) {
60             for(int j = 0 ; j < m ; ++j) {
61                 if(!map[i][j] && (i + j) % 2) {
62                     for(int t = 0 ; t < 4 ; ++t) {
63                         int x = i + tx[t] , y = j + ty[t];
64                         if(check(x , y)) {
65                             G[i*m + j].push_back(x*m + y);
66                         }
67                     }
68                 }
69             }
70         }
71         printf("%s\n" , 2*hungry() == n*m-k ? "YES" : "NO");
72     }
73     return 0;
74 }

 

posted @ 2016-07-12 19:51  Recoder  阅读(628)  评论(0编辑  收藏  举报