二分图的匹配

1|0定义

有点扩展域并查集的意思~

如果一张无向图的 N 个节点 (n2) 可以分成 A,B 两个非空集合,其中 AB=,并且在同一集合内的点之间都没有边相连,那么称这张无向图为一张二分图AB 分别称为二分图的左部和右部。

img

2|0性质

  • 如果两个集合中的点分别染成黑色和白色,可以发现二分图中的每一条边都一定是连接一个黑色点和一个白色点。
  • 二分图不存在长度为奇数的环。
    • 因为每一条边都是从一个集合走到另一个集合,只有走偶数次才可能回到同一个集合。

3|0二分图判定

3|1定理

由性质可推出判定定理:

一张无向图是二分图,当且仅当图中不存在奇环(长度为奇数的环)。

3|2方法

根据该定理,我们可以用染色法进行二分图判定。

大致思想为:

  1. 尝试用黑白两种颜色标记图中的节点。
  2. 当一个节点被标记后,它的所有相邻节点应该被标记为与它相反的颜色。
  3. 若标记过程中产生冲突,说明图中存在奇环。

基于 DFS 的伪代码,时间复杂度为 O(N+M)

void dfs(int x, int color) { 赋值 v[x] <- color 对于与 x 相连的每条无向边 (x,y) if v[y] = 0 then dfs(y, 3 - color);//因为只有1、2两种颜色,3-1 = 2, 3-2 = 1 else if V[y] == color 判定该图 不是二分图,算法结束 } 在主函数中 for i <- 1 to N if v[i] = 0 then dfs(i, 1) 判定无向图 是二分图

3|3例题

对最大冲突值二分答案。

把所有仇恨程度大于当前 mid 的罪犯分到两个集合(在这两个罪犯之间建边)。

这张无向图的节点需要被分成两个集合(两个监狱),并且集合内部没有边(同一个监狱内没有仇恨程度大于 mid 的罪犯)。所以,我们用染色法判定是否为二分图即可。

#include<iostream> #include<algorithm> #include<cstdio> #include<vector> #include<cstring> using ll = long long; const int N = 2e4 + 10; const int M = 1e5 + 10; std::vector<int> v[N]; int vis[N]; int n, m; ll l, r, mid; struct Node{ int x, y; ll value; Node(int _x, int _y, ll _v): x(_x), y(_y), value(_v) {} Node() {} void read() {std::cin >> x >> y >> value; r = std::max(r, value);} void setMap(int t) {if (value > t) v[x].push_back(y), v[y].push_back(x);} }query[M]; void init() { std::cin >> n >> m; int x, y, t; for (int i = 1; i <= m; i++) query[i].read(); } bool dfs(int x, int color) { vis[x] = color; for (auto to : v[x]) { if (vis[to] == 0) { if (!dfs(to, 3 - color)) return false; } else if (vis[to] == color) return false; } return true; } bool check(int x) { memset(vis, 0, sizeof(vis)); for (int i = 1; i <= n; i++) v[i].clear(); for (int i = 1; i <= m; i++) { query[i].setMap(x); } for (int i = 1; i <= n; i++) { if (vis[i] == 0) { if (!dfs(i, 1)) return false; } } return true; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout.tie(nullptr); init(); while(l <= r) { mid = l + ((r - l) >> 1); if (check(mid)) r = mid - 1; else l = mid + 1; } std::cout << r + 1; return 0; }

4|0二分图最大匹配


__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/17887202.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示