poj 2446 poj 1469 poj 1274 二分图最大匹配
2015-05-18 14:26
393 查看
poj 2446:
题意:
给一张m * n的图,其中挖掉一些点,然后用1*2的小纸片来覆盖这张图,问能否将这个图覆盖。
如下图:
解析:
将每个不为挖掉的点视为二分图的X点集,这个点的四个方向上的点视为Y点集,此时最大匹配数即为点的个数(想一想为什么)。
因为有重复匹配 1和2
2和1
这题用一个id数组来处理每个点的id,然后用匈牙利算法求最大匹配就ok了。
代码:
(邻接矩阵版)1552K 172MS
(邻接表) 1492K 94MS
poj 1469:
题意:
给课程和喜欢这门课的学生。
问是否存在每个不同的学生喜欢不同的课。
解析:
最直接的二分图匹配。
代码:
poj 1274
题意:
二分图最大匹配。
代码:
题意:
给一张m * n的图,其中挖掉一些点,然后用1*2的小纸片来覆盖这张图,问能否将这个图覆盖。
如下图:
解析:
将每个不为挖掉的点视为二分图的X点集,这个点的四个方向上的点视为Y点集,此时最大匹配数即为点的个数(想一想为什么)。
因为有重复匹配 1和2
2和1
这题用一个id数组来处理每个点的id,然后用匈牙利算法求最大匹配就ok了。
代码:
(邻接矩阵版)1552K 172MS
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <queue> #include <map> #include <climits> #include <cassert> #define LL long long #define lson lo, mi, rt << 1 #define rson mi + 1, hi, rt << 1 | 1 using namespace std; const int maxn = 33 * 33; const int inf = 0x3f3f3f3f; const double eps = 1e-8; const double pi = acos(-1.0); const double ee = exp(1.0); int dir[][2] = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}}; bool maze[maxn][maxn]; vector<int> g[maxn]; bool vis[maxn]; int fr[maxn]; int m, n, k; int cnt; int id[maxn][maxn]; bool match(int v) { for (int i = 0; i < g[v].size(); i++) { int u = g[v][i]; if (!vis[u]) { vis[u] = true; if (fr[u] == -1 || match(fr[u])) { fr[u] = v; return true; } } } return false; } int hungary() { int ret = 0; memset(fr, -1, sizeof(fr)); for (int i = 1; i <= cnt; i++) { memset(vis, false, sizeof(vis)); if (match(i)) ret++; } return ret; } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL while (~scanf("%d%d%d", &m, &n, &k)) { memset(maze, true, sizeof(maze)); for (int i = 0; i < k; i++) { int x, y; scanf("%d%d", &y, &x); maze[x][y] = false; } if ((m * n - k) % 2) { printf("NO\n"); } else { cnt = 0; for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (maze[i][j]) { id[i][j] = ++cnt; } } } for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (maze[i][j]) { for (int d = 0; d < 4; d++) { int ni = i + dir[d][0]; int nj = j + dir[d][1]; if (1 <= ni && ni <= m && 1 <= nj && nj <= n && maze[ni][nj]) { g[id[i][j]].push_back(id[ni][nj]); } } } } } //cout << hungary() <<endl; if (hungary() + k == m * n) { printf("YES\n"); } else { printf("NO\n"); } } } return 0; }
(邻接表) 1492K 94MS
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <queue> #include <map> #include <climits> #include <cassert> #define LL long long #define lson lo, mi, rt << 1 #define rson mi + 1, hi, rt << 1 | 1 using namespace std; const int maxn = 33 * 33; const int inf = 0x3f3f3f3f; const double eps = 1e-8; const double pi = acos(-1.0); const double ee = exp(1.0); int dir[][2] = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}}; bool maze[maxn][maxn]; bool vis[maxn]; int fr[maxn]; int m, n, k; int cnt; int id[maxn][maxn]; struct edge { int to, next; } e[maxn]; int head[maxn]; int index; void addedge(int u, int v) { e[index].to = v; e[index].next = head[u]; head[u] = index; index++; } bool match(int v) { for (int i = head[v]; i != -1; i = e[i].next) { int u = e[i].to; if (!vis[u]) { vis[u] = true; if (fr[u] == -1 || match(fr[u])) { fr[u] = v; return true; } } } return false; } int hungary() { int ret = 0; memset(fr, -1, sizeof(fr)); for (int i = 1; i <= cnt; i++) { memset(vis, false, sizeof(vis)); if (match(i)) ret++; } return ret; } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL while (~scanf("%d%d%d", &m, &n, &k)) { memset(maze, true, sizeof(maze)); for (int i = 0; i < k; i++) { int x, y; scanf("%d%d", &y, &x); maze[x][y] = false; } if ((m * n - k) % 2) { printf("NO\n"); } else { cnt = 0; for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (maze[i][j]) { id[i][j] = ++cnt; } } } memset(head, -1, sizeof(head)); for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (maze[i][j]) { for (int d = 0; d < 4; d++) { int ni = i + dir[d][0]; int nj = j + dir[d][1]; if (1 <= ni && ni <= m && 1 <= nj && nj <= n && maze[ni][nj]) { addedge(id[i][j], id[ni][nj]); } } } } } //cout << hungary() <<endl; if (hungary() + k == m * n) { printf("YES\n"); } else { printf("NO\n"); } } } return 0; }
poj 1469:
题意:
给课程和喜欢这门课的学生。
问是否存在每个不同的学生喜欢不同的课。
解析:
最直接的二分图匹配。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <queue> #include <map> #include <climits> #include <cassert> #define LL long long #define lson lo, mi, rt << 1 #define rson mi + 1, hi, rt << 1 | 1 using namespace std; const int maxn = 300 + 10; const int inf = 0x3f3f3f3f; const double eps = 1e-8; const double pi = acos(-1.0); const double ee = exp(1.0); vector<int> g[maxn]; int fr[maxn]; bool vis[maxn]; int p, n; bool match(int v) { for (int i = 0; i < g[v].size(); i++) { int u = g[v][i]; if (!vis[u]) { vis[u] = true; if (fr[u] == -1 || match(fr[u])) { fr[u] = v; return true; } } } return false; } int angary() { int ret = 0; memset(fr, -1, sizeof(fr)); for (int i = 1; i <= p; i++) { memset(vis, false, sizeof(vis)); if (match(i)) { ret++; } } return ret; } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL int ncase; scanf("%d", &ncase); while (ncase--) { for (int i = 0; i < maxn; i++) g[i].clear(); scanf("%d%d", &p, &n); for (int i = 1; i <= p; i++) { int k; scanf("%d", &k); while (k--) { int x; scanf("%d", &x); g[i].push_back(x); } } // cout << angary() << endl; if (angary() == p) printf("YES\n"); else printf("NO\n"); } return 0; }
poj 1274
题意:
二分图最大匹配。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <queue> #include <map> #include <climits> #include <cassert> #define LL long long #define lson lo, mi, rt << 1 #define rson mi + 1, hi, rt << 1 | 1 using namespace std; const int maxn = 200 + 10; const int inf = 0x3f3f3f3f; const double eps = 1e-8; const double pi = acos(-1.0); const double ee = exp(1.0); vector<int> g[maxn]; int fr[maxn]; bool vis[maxn]; int n, m; bool match(int v) { for (int i = 0; i < g[v].size(); i++) { int u = g[v][i]; if (!vis[u]) { vis[u] = true; if (fr[u] == -1 || match(fr[u])) { fr[u] = v; return true; } } } return false; } int hungary() { int ret = 0; memset(fr, -1, sizeof(fr)); for (int i = 1; i <= n; i++) { memset(vis, false, sizeof(vis)); if (match(i)) { ret++; } } return ret; } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL while (~scanf("%d%d", &n, &m)) { for (int i = 0; i <= n; i++) g[i].clear(); for (int i = 1; i <= n; i++) { int k; scanf("%d", &k); while (k--) { int x; scanf("%d", &x); g[i].push_back(x); } } printf("%d\n", hungary()); } return 0; }
相关文章推荐
- POJ 1274 / POJ 1469 / POJ 2239 二分图最大匹配
- POJ 1274 / POJ 1469 / POJ 2239 二分图最大匹配
- [POJ] 1274 The Perfect Stall(二分图最大匹配)
- [POJ] 2446 Chessboard(二分图最大匹配)
- POJ 1469 二分图最大匹配
- POJ 2446 Chessboard (二分图最大匹配)
- POJ - 1274 The Perfect Stall 二分图 最大匹配
- 【POJ1469】Courses-二分图最大匹配
- Poj 1274 The Perfect Stall[二分图最大匹配]
- poj 1469(二分图 最大匹配)
- poj 2446 Chessboard(二分图最大匹配)
- poj 1274 二分图最大匹配
- poj2446 && poj1469 二分图最大匹配
- POJ1469(匈牙利算法求二分图最大匹配)
- POJ 1469 COURSES(二分图最大匹配) (矩阵和邻接表的模板题)
- poj 1469 COURSES (二分图最大匹配)
- 二分图最大匹配题目汇总 POJ 1274、2239、3020、3715
- POJ 1469 二分图最大匹配
- 利用匈牙利算法&Hopcroft-Karp算法解决二分图中的最大二分匹配问题 例poj 1469 COURSES
- POJ 1274--The Perfect Stall【二分图 && 最大匹配数 && 水题】