• 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 }
  • 相关阅读:
    ManualResetEvent详解
    MEF搜索范围
    ThreadStart和ParameterizedThreadStart区别
    快速理解C#高级概念(一) Delegate委托
    c# 多线程 --Mutex(互斥锁)
    sql server 得到数据库字典
    遇到的坑:在线用户统计的实现
    asp.net core 使用EF7 Code First 创建数据库,同时使用命令创建数据库
    使用cachemanager做缓存(Session的缓存)
    C# web api返回类型设置为json的两种方法
  • 原文地址:https://www.cnblogs.com/Missa/p/2997960.html
Copyright © 2020-2023  润新知