U64949 棋盤覆蓋(二分圖)
阿新 • • 發佈:2020-08-11
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^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; }