POJ 2446 Chessboard(奇偶建点法+最大匹配)
2017-08-18 01:18
351 查看
题目地址
题意:你有很多1*2的小纸条,你有一个棋盘,棋盘上有许多空洞,空洞上面是不能放小纸条的,要你求出这个棋盘除了空洞以外的所有格子能不能被小纸条覆盖
思路:我不知道为什么通过吧(x,y)坐标化成x*m+y的形式去存是不行的(没有想明白),只有用奇偶建点发才行。
奇偶建点法就是因为他要由相邻的两个块组成一个1*2的块,所有这两个块的(x+y)是一奇一偶的,所以可以用奇偶去表示这两个块。
因为我的是建双向边所以在最后算结果的时候因为每个1*2的块都算了两次,所以就不用再乘二了。
题意:你有很多1*2的小纸条,你有一个棋盘,棋盘上有许多空洞,空洞上面是不能放小纸条的,要你求出这个棋盘除了空洞以外的所有格子能不能被小纸条覆盖
思路:我不知道为什么通过吧(x,y)坐标化成x*m+y的形式去存是不行的(没有想明白),只有用奇偶建点发才行。
奇偶建点法就是因为他要由相邻的两个块组成一个1*2的块,所有这两个块的(x+y)是一奇一偶的,所以可以用奇偶去表示这两个块。
因为我的是建双向边所以在最后算结果的时候因为每个1*2的块都算了两次,所以就不用再乘二了。
#include <iostream> #include <cstring> #include <string> #include <queue> #include <vector> #include <map> #include <set> #include <stack> #include <cmath> #include <cstdio> #include <algorithm> #define N 3010 #define LL __int64 #define inf 0x3f3f3f3f #define lson l,mid,ans<<1 #define rson mid+1,r,ans<<1|1 #define getMid (l+r)>>1 #define movel ans<<1 #define mover ans<<1|1 using namespace std; const LL mod = 1e9 + 7; int n, m; int tmp1, tmp2; int path ; struct Hungarian { vector<int> mapp ; bool vis ;//是否为匹配点 int mark ;//该边与哪个点构成的边为匹配边 void init() { for (int i = 0; i <= n + m + 20; i++) { mapp[i].clear(); } memset(mark, -1, sizeof(mark)); } void add(int a, int b) { mapp[a].push_back(b); mapp[b].push_back(a); } bool dfs(int u) { for (int i = 0; i < mapp[u].size(); i++) { int v = mapp[u][i]; if (!vis[v]) { vis[v] = true; if (mark[v] == -1 || dfs(mark[v])) { mark[u] = v; mark[v] = u; return true; } } } return false; } int solve() { int sum = 0; for (int i = 1; i < tmp1; i++) {//枚举非匹配点 if (mark[i] == -1) { memset(vis, false, sizeof(vis)); if (dfs(i)) { sum++;//最大匹配的个数 } } } return sum; } }hungarian; int main() { int x, y; int q; cin.sync_with_stdio(false); while (cin >> n >> m >> q) { hungarian.init(); memset(path, 0, sizeof(path)); for (int i = 1; i <= q; i++) { cin >> x >> y; path[y][x] = -1; } tmp1 = 1, tmp2 = 1;//奇偶建边 for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (path[i][j] == 0) { if ((i + j) / 2) {//奇数 path[i][j] = tmp1++; } else { path[i][j] = tmp2++; } } } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (path[i][j] != -1 && (i + j) / 2) { if (path[i - 1][j] > 0) { hungarian.add(path[i][j], tmp1 + path[i - 1][j]); } if (path[i + 1][j] > 0) { hungarian.add(path[i][j], tmp1 + path[i + 1][j]); } if (path[i][j - 1] > 0) { hungarian.add(path[i][j], tmp1 + path[i][j - 1]); } if (path[i][j + 1] > 0) { hungarian.add(path[i][j], tmp1 + path[i][j + 1]); } } } } /*for (int i = 1; i < n; i++) { for (int j = 1; j < m; j++) { if (path[i][j] != -1) { if (path[i][j + 1] != -1) { hungarian.add(i*m + j, i*m + j + 1); } if (path[i + 1][j] != -1) { hungarian.add(i*m + j, (i + 1)*m + j); } } } }*/ if (hungarian.solve() == n*m - q) { cout << "YES" << endl; } else { cout << "NO" << endl; } } return 0; }
相关文章推荐
- [POJ] 2446 Chessboard(二分图最大匹配)
- POJ 2446 Chessboard(二分图最大匹配)
- POJ 2446 Chessboard 二分图的最大匹配 <建图>
- POJ - 2446 Chessboard 二分图 最大匹配(输入坑)
- POJ-2446 Chessboard 最大匹配
- poj--2446 Chessboard(二分图最大匹配)
- poj 2446 Chessboard 二分图最大匹配经典题
- POJ 2446 Chessboard (二分图最大匹配)
- POJ 2446-Chessboard(二分图_最大匹配)
- poj 2446 Chessboard(二分图最大匹配)
- POJ 2446 Chessboard(二分图最大匹配)
- poj Chessboard 2446 (最大匹配&转换)
- POJ 2446 Chessboard(二分图最大匹配)
- 【二分图+最大匹配】北大 poj 2446 Chessboard
- POJ 2446Chessboard(二分图最大匹配)
- poj 2446 Chessboard 二分图的最大匹配
- POJ2446 Chessboard【二分图最大匹配】
- poj 2446 Chessboard (最大二分匹配)
- POJ 2446 Chessboard(二分图最大匹配)
- poj 2446 二分图 最大匹配