POJ 2446 Chessboard (二分图匹配)

题意

在一个N*M的矩形里,用1*2的骨牌去覆盖该矩形,每个骨牌只能覆盖相邻的两个格子,问是否能把每个格子都盖住。PS:有K个孔不用覆盖。

思路

容易发现,棋盘上坐标和为奇数的点只会和坐标和为偶数的点相邻,所以这是个二分图.而每两个格子对应一个骨牌,并且一个格子只能被一个骨牌覆盖,这样就联想到了二分图匹配。把图中能覆盖的格子从1 依次标号 若格子数为奇数 答案是NO 否则,把相邻的两个标号能连成一条边,求无向图的二分匹配数,当匹配数 == 格子数时,就能覆盖完。

代码

 
#include 
#include 
#include 
#include 
#include 
#include 
#define MID(x,y) ((x+y)/2)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXV = 2005;                   //N1+N2
vector  adj[MAXV];
struct MaximumMatchingOfBipartiteGraph{
    int vn;
    void init(int n){                   //二分图两点集点的个数
        vn = n;
        for (int i = 0; i <= vn; i ++)     adj[i].clear();
    }
    void add_uedge(int u, int v){
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    bool vis[MAXV];
    int mat[MAXV];                      //记录已匹配点的对应点
    bool cross_path(int u){
        for (int i = 0; i < (int)adj[u].size(); i ++){
            int v = adj[u][i];
            if (!vis[v]){
                vis[v] = true;
                if (mat[v] == 0 || cross_path(mat[v])){
                    mat[v] = u;
                    mat[u] = v;
                    return true;
                }
            }
        }
        return false;
    }
    int hungary(){
        mem(mat, 0);
        int match_num = 0;
        for (int i = 1; i <= vn; i ++){
            mem(vis, 0);
            if (!mat[i] && cross_path(i)){
                match_num ++;
            }
        }
        return match_num;
    }
}match;
bool hole[35][35];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
void build(int m, int n){
    for (int i = 1; i <= m; i ++){
        for (int j = 1; j <= n; j ++){
            if (!hole[i][j]){
                for (int direction = 0; direction < 4; direction ++){
                    int x = i + dx[direction], y = j + dy[direction];
                    if (x > 0 && x <= m && y > 0 && y <= n && hole[x][y] == false){
                        match.add_uedge((i-1)*n+j, (x-1)*n+y);
                    }
                }
            }
        }
    }
}
int main(){
	//freopen("test.in", "r", stdin);
	//freopen("test.out", "w", stdout);
	int m, n, k;
	while(scanf("%d %d %d", &m, &n, &k) != EOF){
        mem(hole, 0);
        for (int i = 0; i < k; i ++){
            int y, x;
            scanf("%d %d", &y, &x);
            hole[x][y] = true;
        }
        if ((m * n - k) % 2 == 1){
            puts("NO");
        }
        else{
            int num = (m * n - k) / 2;
            match.init(m*n);
            build(m, n);
            if (match.hungary() == num){
                puts("YES");
            }
            else{
                puts("NO");
            }
        }
	}
	return 0;
}
原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114068.html