当前位置:网站首页>图论:二分图
图论:二分图
2022-07-29 23:55:00 【*﹏ℳ๓无情*】
二分图
简介
无向图中的顶点可以分为两个交集为空的集合X和Y,对于图中的每条边,其中一个端点在X中,另外一个端点在Y中,且X和Y内部的顶点之间没有边。
集合X和Y中每对顶点之间都有且仅有一条边的图称为完全二分图,可以记作 K n , m K_{n,m} Kn,m,n和m分别为X和Y集合中的顶点个数。
判定方法
染色法:
每次选择一个未被染色的顶点x,先将其染为黄色,接着从x除法做dfs遍历x所在的连通块。
在dfs的过程中,假如现在枚举到了边u→v,如果v还没有被染色,则把v染成和u不同的颜色,否则如果u和v颜色相同,则说明此图不是二分图。
如果能顺利遍历完图中所有的连通块,则此图为二分图。
vector<int> edge[N];
int n, m, c[N];
//染色
bool dfs(int x)
{
for (auto y : edge[x])
if (!c[y])
{
c[y] = 3 - c[x];
if (!dfs(y))
return false;
}
else if (c[x] == c[y])
return false;
return true;
}
bool check()
{
memset(c, 0, sizeof c);
for (int i = 1; i <= n; i++)
if (!c[i])
{
c[i] = 1;
if (!dfs(i))
return false;
}
return true;
}
二分图最大匹配
简介
将二分图G=<V,E>的顶点集V拆分为 V 1 V_1 V1, V 2 V_2 V2, ∣ V 1 ∣ ≤ ∣ V 2 ∣ |V_1|≤|V_2| ∣V1∣≤∣V2∣,选取一些边E’⊆E;
如果E’中任意两条边都没有相同的顶点,则称E’为G的匹配;
G中边数最多的匹配称为G的最大匹配,其中包含的边数称为G的匹配数;
如果G的最大匹配包含的边数 = ∣ V 1 ∣ =|V_1| =∣V1∣,则称此匹配为完备匹配。
一组最大匹配,也是完备匹配。
交错路径:如果P是G中的一条路径,并且对于P上每一对相邻的边(端点包含同一个顶点),都满足其中一条在匹配M中,而另一条不在。
增广路径:一条交错路径的路径的起点和终点都未被匹配的路径叫做增广路径。
如果我们能找到增广路径P,那么M⊕P(对于一条边,如果它在M中出现不在P中出现或是在P中出现不在M中出现)就是一组更优的匹配。
判定(匈牙利算法)
通过不断寻找新的增广路,来优化现有的匹配。
时间复杂度: O ( n m ) O(nm) O(nm)
vector<int> edge[N];
int n, m, n1, n2, v[N];
bool b[N];
bool find(int x)
{
b[x] = true;
for (auto y : edge[x])
{
if (!v[y] || (!b[v[y]] && find(v[y])))
{
v[y] = x;
return true;
}
}
return false;
}
int match()
{
int ans = 0;
memset(v, 0, sizeof v);
for (int i = 1; i <= n1; i++)
{
memset(b, false, sizeof b);
if (find(i))
++ans;
}
return ans;
}
最大独立集
在图中选出最多的点,满足他们两两之间没有边相连
最大独立集 = n − 最大匹配数 最大独立集=n-最大匹配数 最大独立集=n−最大匹配数
最小点覆盖
选出最少的点至少包含二分图的每条边的两个点中的一个。
最小点覆盖 = 最大匹配数 最小点覆盖=最大匹配数 最小点覆盖=最大匹配数
棋盘转二分图
vector<int> edge[N];
int n, m, n1, n2;
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
int a[N][N]; //棋盘中不能放置的点
int r[N][N]; //存储棋盘(二分图)中左右两边点的编号
scanf("%d%d", &n, &m); // n*n的棋盘,有m个不可放置的点
memset(a, 0, sizeof a);
n1 = n2 = 0;
for (int i = 1; i <= m; i++)
{
int x, y;
scanf("%d%d", &x, &y);
a[x][y] = 1;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (!a[i][j])
if ((i + j) & 1)
r[i][j] = ++n2;
else
r[i][j] = ++n1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (!a[i][j] && !((i + j) & 1))
for (int k = 0; k < 4; k++)
{
int x = i + dx[k], y = j + dy[k];
if (x < 1 || x > n || y < 1 || y > n || a[x][y])
continue;
edge[r[i][j]].push_back(r[x][y]);
}
转换成二分图问题(拆点)
将一个点拆成一个进去的点和一个出去的点,观察是否可以装换成匹配问题。
边栏推荐
- call、apply 以及 bind 的区别和用法
- Decision tree principle and code implementation
- 全国双非院校考研信息汇总整理 Part.6
- 论文精读——YOLOv3: An Incremental Improvement
- Brute force recursion to dynamic programming 03 (knapsack problem)
- C陷阱与缺陷 第5章 库函数 5.4 使用errno检测错误
- Apache Doris 1.1 特性揭秘:Flink 实时写入如何兼顾高吞吐和低延时
- 【集训DAY16】ALFA【凸壳】【计算几何】
- ZLMediaKit源码分析 - NotifyCenter
- CesiumJS 2022^ 源码解读[0] - 文章目录与源码工程结构
猜你喜欢
First Normal Form, Second Normal Form, Third Normal Form
【集训DAY18】有趣的交换【模拟】【数学】
软件测试拿8k以上有多简单,掌握这些随随便便拿8k以上...
第一范式、第二范式、第三范式
vim相关介绍(二)
18 Lectures on Disassembly of Multi-merchant Mall System Functions
Paper Intensive Reading - YOLOv3: An Incremental Improvement
学会使用MySQL的Explain执行计划,SQL性能调优从此不再困难
指令集数据产品如何设计和实现报表协同系统——基于指令集物联网操作系统的工业协同制造项目开发实践
Sentinel入门
随机推荐
全国双非院校考研信息汇总整理 Part.3
Wincc报表教程(SQL数据库的建立,wincc在数据库中保存和查询数据,调用Excel模板把数据保存到指定的位置和打印功能)
437. The total path III low low
1326. 灌溉花园的最少水龙头数目 动态规划
29岁从事功能测试被辞,面试2个月都找不到工作吗?
读书笔记:《这才是心理学:看穿伪心理学的本质(第10版)》
rk-boot框架实战(1)
leetcode122. Best Time to Buy and Sell Stock II 买卖股票的最佳时机 II(简单)
C陷阱与缺陷 第4章 链接 4.4 形参、实参与返回值
Add, delete, modify and query the database
Expansion of Parallel I/O Port in Single Chip Microcomputer Development
彻底搞懂kubernetes调度框架与插件
第一范式、第二范式、第三范式
y81. Chapter 4 Prometheus Factory Monitoring System and Actual Combat -- Monitoring Extension (12)
全国双非院校考研信息汇总整理 Part.1
vim相关介绍(三)
Elephant Swap:借助ePLATO提供加密市场的套利空间
devops学习(三) K8环境部署jenkins
Sentinel入门
C陷阱与缺陷 第4章 链接 4.2 声明与定义