U64949 棋盘覆盖(二分图)

Posted riotian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了U64949 棋盘覆盖(二分图)相关的知识,希望对你有一定的参考价值。

https://ac.nowcoder.com/acm/contest/1062/B

【题目】

给出一张n×n(n≤100)的国际象棋棋盘,其中被删除了一些点,问可以使用多少1*2的多米诺骨牌进行掩盖。

【题意】

题意简单,不做多说明,多米诺骨牌可以理解为长方形的方块。

【题解】

仔细一想,可以发现能用二分图来做。即可以把每个位置的点进行重新编号,相邻的两点具有不同的性质。比如说在2×2的图内第一个点((1,1))标记为1,它是奇数,那么与它相邻的((1,2)(1,2))就要标记成偶数。又比如在3×3的图内的点((2,2))为奇数,那么((1,2),(2,1)(2,3),(3,2))的点就要标记为偶数。然后两两建边,奇数点->偶数点 or 偶数点->奇数点(当然如果是被删除的点,则不能建边)。最后对 偶数点 or 奇数点 跟 奇数点 or 偶数点 进行二分图匹配即可。

时间复杂度:(O(N^2M^2))

#include<bits/stdc++.h>
using namespace std;
const int N = 110;
const int dx[] = { 0,1,0,-1 };
const int dy[] = { 1,0,-1,0 };
int n, m, ans, f[N * N];
bool b[N][N], v[N * N];
vector<int>e[N * N];

bool dfs(int x) {
    for (unsigned int i = 0; i < e[x].size(); i++) {
        int y = e[x][i];
        if (v[y]) continue;
        v[y] = 1;
        if (f[y] == -1 || dfs(f[y])) {
            f[y] = x;return 1;
        }
    }
    return 0;
}

int main() {
    //freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(false), cin.tie(0);
    cin >> n >> m;
    while (m--) {
        int x, y; cin >> x >> y;
        b[x - 1][y - 1] = 1;
    }
    for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			if (!b[i][j])
				for (int k = 0; k < 4; k++) {
					int x = i + dx[k], y = j + dy[k];
					if (x >= 0 && x < n && y >= 0 && y < n && !b[x][y]) {
						e[i*n+j].push_back(x * n + y);
						e[x*n+y].push_back(i * n + j);
					}
				}
    memset(f, -1, sizeof(f));
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++) {
            if ((i ^ j) & 1) continue;
            memset(v, 0, sizeof(v));
            ans += dfs(i * n + j);
        }
    cout << ans << endl;
}

以上是关于U64949 棋盘覆盖(二分图)的主要内容,如果未能解决你的问题,请参考以下文章

棋盘覆盖TYVJ1035(二分图最大匹配)

CH6801棋盘覆盖(二分图最大匹配)

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

棋盘覆盖 题解

四个点的圈是二分图吗

图论二分图的应用(染色法判断二分图,最大匹配,最小点覆盖,最大独立集,最小路径点覆盖,最小路径重复点覆盖)