POJ-2446-Chessboard(二分图匹配)

链接:https://vjudge.net/problem/POJ-2446#author=0

题意:

有一天,罗老板画了一块尺寸为M * N的棋盘。他希望许老师能够使用1 * 2的牌来覆盖棋盘。然而,他认为这很容易,所以他增大了难度,他在棋盘上打了一些洞 

许老师必须遵守以下规则: 
1.任何不是洞网格都应该只被一张卡覆盖。 
2. 一张卡应该正好覆盖2个相邻非洞网格。 
3. 洞不可以被卡片覆盖

你的任务是帮助许老师确定 根据上述规则 是否存在一种方案可以覆盖棋盘

思路:

二分图匹配.因为一个1*2的方块,所放的两个格子,一个格子的x+y是偶数,一个是奇数,所以可以以x+y根据奇偶建图,再去求二分图。

代码:

#include <iostream>
#include <memory.h>
#include <string>
#include <istream>
#include <sstream>
#include <vector>
#include <stack>
#include <algorithm>
#include <map>
#include <queue>
#include <math.h>
#include <cstdio>
#include <set>
#include <iterator>
#include <cstring>
using namespace std;

typedef long long LL;
const int MAXN = 2000;
int Next[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};

int Dis[40][40];
int G[MAXN][MAXN];
int Link[MAXN];
bool Used[MAXN];
int n, m, k;
int cnt1, cnt2;

bool Dfs(int x)
{
    for (int node = 1;node <= cnt2;node++)
    {
        if (G[x][node] == 1 && Used[node] == false)
        {
            Used[node] = true;
            if (Link[node] == -1 || Dfs(Link[node]))
            {
                Link[node] = x;
                return true;
            }
        }
    }
    return false;
}

int Solve()
{
    int res = 0;
    memset(Link, -1, sizeof(Link));
    for (int i = 1;i <= cnt1;i++)
    {
        memset(Used, 0, sizeof(Used));
        if (Dfs(i))
            res++;
    }
    return res;
}

int main()
{
    while (cin >> n >> m >> k)
    {
        memset(Dis, 0, sizeof(Dis));
        int y, x;
        for (int i = 1;i <= k;i++)
        {
            cin >> y >> x;
            Dis[x][y] = -1;
        }
        cnt1 = cnt2 = 0;
        for (int i = 1;i <= n;i++)
        {
            for (int j = 1;j <= m;j++)
            {
                if (Dis[i][j] != -1)
                {
                    if ((i+j)%2 == 0)
                        Dis[i][j] = ++cnt1;
                    else
                        Dis[i][j] = ++cnt2;
                }
            }
        }
        for (int i = 1;i <= n;i++)
        {
            for (int j = 1;j <= m;j++)
            {
                if (Dis[i][j] != -1 && (i+j)%2 == 0)
                {
                    for (int k = 0;k < 4;k++)
                    {
                        int tx = i+Next[k][0];
                        int ty = j+Next[k][1];
                        if (tx < 1 || tx > n || ty < 1 || ty > m)
                            continue;
                        G[Dis[i][j]][Dis[tx][ty]] = 1;
                    }
                }
            }
        }
        if ((n*m-k)%2 == 1 || cnt1 != cnt2)
        {
            cout << "NO" << endl;
            continue;
        }
        int res = Solve();
        if (res == (n*m-k)/2)
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }

    return 0;
}

  

原文地址:https://www.cnblogs.com/YDDDD/p/10859069.html