二分图 _ 复习
学习请看
染色法判断二分图
基础
题意:
给定一个 N 行 N 列的棋盘,已知某些格子禁止放置。
求最多能往棋盘上放多少块的长度为 2、宽度为 1 的骨牌,并且任意两张骨牌都不重叠。
思路:
代码:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #define int long long using namespace std; const int N = 20010, M = 200010; int n, m; int to[M], pre[M], w[M], h[N], idx; int color[N]; void add(int a, int b, int c) { to[idx] = b, w[idx] = c, pre[idx] = h[a], h[a] = idx++; } bool dfs(int u, int c, int x) { color[u] = c; for (int i = h[u]; i != -1; i = pre[i]) { if (w[i] <= x) continue; int j = to[i]; if (color[j]) { if (color[j] == c) return false; } else if (!dfs(j, 3 - c, x)) return false; } return true; } bool check(int x) { memset(color, 0, sizeof color); for (int i = 1; i <= n; i++) { if (color[i] == 0) { if (!dfs(i, 1, x)) return false; } } return true; } signed main() { memset(h, -1, sizeof h); cin >> n >> m; for (int i = 0; i < m; i++) { int a, b, c; cin >> a >> b >> c; add(a, b, c); add(b, a, c); } int l = 0, r = 1e9; while (l < r) { int mid = (l + r) / 2; if (check(mid)) r = mid; else l = mid + 1; } cout << l << endl; return 0; }
匈牙利算法找最大匹配
最大匹配: 边数最多的一组匹配
增广路径: 非匹配点 非匹配边 匹配边 非匹配边 匹配边 非匹配点
最大匹配等价于不存在增广路径
题意:
给定一个 N 行 N 列的棋盘,已知某些格子禁止放置。
求最多能往棋盘上放多少块的长度为 2、宽度为 1 的骨牌,并且任意两张骨牌都不重叠。
思路:
将放置骨牌看成连边。
将图看成黑白相间图,白格子周围都是黑格子。
显然放置骨牌连边等价于对不同颜色的点连边。
因此最大骨牌放置量,就是二分图的最大匹配。
代码:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #define int long long using namespace std; const int N = 510, M = 2e5 + 10; int n1, n2, m; int to[M], pre[M], h[N], idx; int match[N]; int st[N]; void add(int a, int b) { to[idx] = b, pre[idx] = h[a], h[a] = idx++; } bool find(int x) { for (int i = h[x]; i != -1; i = pre[i]) { int j = to[i]; if (st[j]) continue; st[j] = true; if (match[j] == 0 || find(match[j])) { match[j] = x; return true; } } return false; } signed main() { memset(h, -1, sizeof h); cin >> n1 >> n2 >> m; for (int i = 0; i < m; i++) { int a, b; cin >> a >> b; add(a, b); } int res = 0; for (int i = 1; i <= n1; i++) { memset(st, 0, sizeof st); if (find(i)) res++; } cout << res << endl; return 0; }
最小点覆盖、最大独立集、最小路径点覆盖、最小路径重复点覆盖
最大匹配数 = 最小点覆盖 = 总点数 - 最大独立集 = 总点数 - 最小路径覆盖
二分图中,最小点覆盖 等于 最大匹配数!
最优匹配 KM算法
多重匹配
本文作者:kingwzun
本文链接:https://www.cnblogs.com/kingwz/p/16481193.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
标签:
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步