其他分享
首页 > 其他分享> > 二分图学习笔记(二分图判定及二分图最大匹配)

二分图学习笔记(二分图判定及二分图最大匹配)

作者:互联网

二分图判定

定理:一张无向图是二分图,当且仅当途中不存在奇环(长度为奇数的环)
依据此定理,我们可以用染色法进行二分图的判定。大致思想为:尝试用黑白(c = 0或1)两种颜色标记图中的结点。当一个节点被标记后,它的所有相邻节点被标记为与它相反的颜色(c ^ 1)。若标记过程中产生冲突,则说明图中存在奇环。实现代码如下:

点击查看代码
inline bool dfs(int cur, int c) {
	colour[cur] = c;
	for (int i = head[cur]; i; i = nxt[i]) {
		if (colour[to[i]] == -1) {
			if (dfs(to[i], c ^ 1) == 1)
				return 1;
		}
		else if (colour[to[i]] == c)
			return 1;
	}
	return 0;
}

时间复杂度为O (N + M)

二分图最大匹配

“任意两条边都没有公共端点”的边的集合被称为图的一组匹配。在二分图中,包含边数最多的一组匹配被称为二分图的最大匹配。如果在二分图中存在一条连接两个非匹配点的路径 path, 使得非匹配边与匹配边在 path 上交替出现,那么撑 path 就是这张二分图的增广路
显而易见,增广路具有两条性质:

  1. 长度 len 是奇数。
  2. 路径上第1、3、5、……、len条边是非匹配边,第2、4、6、……、len - 1 条边是匹配边,即匹配边与非匹配边交替出现

由第二条性质可知,二分图的一组匹配 S 是最大匹配,当且仅当图中不存在 S 的增广路。证明:

反证法: 假设对于二分图的最大匹配 S,图中存在 S 的增广路。
由性质二可知:将增广路上的边取反(原先的匹配边变为非匹配边,原先的非匹配边变为匹配边),则新得到的边集 S' 仍然是一组匹配,且匹配边数比 S 增加了1。故假设不成立。
证毕。

匈牙利算法(增广路算法、月老算法

匈牙利算法用于计算二分图的最大匹配,其核心思想为不断寻找增广路,并将找到的增广路取反。匈牙利算法的关键也正是在于如何找到一条增广路。代码如下:

点击查看代码
inline bool find(int x) {
	for (int i = head[x]; i; i = nxt[i]) {
		int j = to[i];
		if (mark[j] == 0) {
			mark[j] = 1;
			if (match[j] == 0 || find(match[j]) == 1) {
				match[j] = x;
				return 1;
			}
		}
	}
	return 0;
}

for (int i = 1; i <= n1; i++) { // 在main函数中
	memset(mark, 0, sizeof(mark));
	if (find(i) == 1)
		ans++;
}

整个实现过程中似乎并没有寻找增广路的过程,但我们经过思考后可以发现,当左部点 x 进行匹配时,有这么两种可能:

  1. 右部点 y 本身就是非匹配点,此时无向边(x, y ) 本身就是非匹配边,自己能够给构成一条长度为1的增广路。
  2. 右部点 y 已经与左部点 x' 匹配,但如果从 x'出发能够找到另一个未匹配的右部点 y' 与之相匹配,则路径 x ~ y ~ x' ~ y' 为一条增广路。如果找不到那就算了

匈牙利算法再是显示采用深搜的框架,递归的从 x 出发寻找增广路。若找到,则在回溯是,中号可以吧路径上的匹配状态取反。另外,可以用全局的 bool 数组标记右部点的访问情况,以防重复搜索。
匈牙利算法的正确性基于贪心策略,即:当一个节点成为匹配点后,最多因找到增广而更换匹配对象,但绝不会再次变回非匹配点。
最后,对于每个左部节点,寻找增广路最多遍历整张二分图一次。因此,匈牙利算法的时间复杂度最差O(NM),实际情况下一般远低于 O(NM)

标签:二分,匹配,增广,int,笔记,算法,判定,return
来源: https://www.cnblogs.com/Nebula-Astraea/p/15977806.html