zoukankan      html  css  js  c++  java
  • 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
    " , 2*hungry() == n*m-k ? "YES" : "NO");
    72     }
    73     return 0;
    74 }
  • 相关阅读:
    1101. Quick Sort (25)
    1100. Mars Numbers (20)
    1099. Build A Binary Search Tree (30)
    TCP四次挥手为何需要TIME_WAIT以及为何是2MSL?
    关于priority_queue运算符重载的问题
    leetcode151.翻转字符串里的单词
    华为笔试题--最长公共子串
    华为笔试题--表达式求值
    华为笔试题--字符串合并处理
    华为笔试题--删除字符串中出现次数最少的字符
  • 原文地址:https://www.cnblogs.com/Recoder/p/5664671.html
Copyright © 2011-2022 走看看