二分图匹配相关概念及内容

这里的概念比较多容易混淆,而且出题时这种可能会针对这些内容直接出结论题,整理一下

  • 二分图的概念

如果一个图可以将其顶点分成两个互不相交的子集,且图中的每条边所连的两个点分属这两个子集,那么这个图可以称作二分图。
一个无向图GG为二分图的充要条件是,GG至少有两个顶点,且其所有回路的长度均为偶数。所以说判断奇环也就是判断二分图。二分图的判断可以用二分图染色,就是使左边的点集是一个颜色右边的点集是一个颜色,dfsdfsbfsbfs都可以实现。

  • 二分图最大匹配

二分图匹配就是求出一个原图的子图使得任意两条边不连在同一个顶点上。
最大匹配就是一个使得子图边数最多的匹配。

匈牙利算法是在二分图问题中很常用的一种算法,作用就是来求最大匹配。
主要流程如下:
枚举左侧的点AA看这个点是否有连向右侧的边,如果有并且连向的这个点BB没有被匹配,那么标记这两个点匹配成功;如果右侧有边的点BB已经被匹配了,那就“协商”,让这个匹配右侧点BB的左侧点CC再去匹配另一个右侧点DD,看是不是能给当前点AA空出位置来,如果可以那么就让CC去匹配DDAA来匹配BB,思想就是如此。

可以发现已经匹配的点不会在接下来的算法流程中失配,最多只会更换匹配的对象。
算法中首先需要遍历每个点,然后再让每个点找连向右侧的边,复杂度Θ(nm)\Theta(nm)
由于经常会遍历到没有匹配的点或没有边连向的点,所以普遍是跑不满的。
洛谷P3386 【模板】二分图匹配

#include <bits/stdc++.h>
#define A 1010

using namespace std;
int g[A], n, m, e, ans; bool f[A][A], vis[A];
int find(int x) {
	for (int i = 1; i <= m; i++)
		if (f[x][i] and !vis[i]) { //如果有边连向这个点并且这个点没有被访问过
			vis[i] = 1; //标记访问,已经匹配过的点就不用再匹配了
			if (!g[i] or find(g[i])) { //如果它还没有被匹配或协商之后可以给x腾出位置
				g[i] = x; //标记与哪个点匹配了
				return true;
			}
		}
	return false;
}
int main(int argc, char const *argv[]) {
	cin >> n >> m >> e; //n,m,e分别为左图点数,右图点数和总边数
	for (int i = 1, x, y; i <= e; i++) cin >> x >> y, f[x][y] = 1; //有边就标记为1
	for (int i = 1; i <= n; i++) if (find(i)) memset(vis, 0, sizeof vis), ans++; //对每个点找匹配对象
	cout << ans << endl; //vis要每次清空,vis标记的是一个右侧点是否被匹配过
}

二分图的最大匹配还可以直接用网络流来做,DinicDinic的话复杂度Θ(nm)\Theta(n\sqrt{m})
具体做法就是在左边建立超级源点,在右边建立超级汇点,超级源点向左侧点连边,右侧点向超级汇点连边,中间的边不变,边的流量都是11,这个图的最大流就是二分图的最大匹配。

二分图匹配中还有一个概念叫增广路
增广路是指,从一个未匹配点开始,经过若干个匹配点,最后到达对面集合的一个未匹配点的路径。即这条路径将两个不同集合的两个未匹配点通过一系列匹配点相连。将增广路与原匹配的边取反后可以得到一个更大的匹配,这里的取反就是增广路中的边变成匹配的,之前匹配的边变成未匹配的。
增广路的路径长度必定为奇数,第一条边和最后一条边都不属于当前匹配。奇数边比偶数边多一条,于是当我们把所有奇数边都加到匹配子图并把偶数边都删除,匹配数就会增加11
一个子图MM为原图GG的最大匹配当且仅当不存在MM的增广路径。

  • 带权二分图匹配

上面的二分图最大匹配可以看成每条边的权值都是11,我们需要找到一个权值最大的匹配。
对于带权的二分图,它的最优匹配一定是一个完备匹配,就是说匹配到的点数是左右侧点数的最小值。
由于是完备匹配,所以原先没有的边需要连上,边权为00即可。

专门求解带权二分图最优匹配的一种算法叫KMKM算法,可惜我并没有学过,所以我会选择用费用流来做带权二分图匹配。
二分图问题是网络流问题的特殊模型,所以基本都可以用网络流的知识来做。

  • 最大独立集

一个图的独立集是一个点集,其中这些点两两之间没有边相连。点数最多的独立集叫这个图的最大独立集。
再介绍一个引申概念,图的团。图的团就是一些点两两之间都有边相连。最大团就是点数最多的团。
一般图的最大独立集是NPNP问题,现在还没有通用解法。但是对于特殊的二分图就有做法。

下面是一些定理,也是结论,题目中可能会用到:

  1. 无向图的最大团 = 这个图补图的最大独立集
  2. 最大独立集 = 点的总数 – 最小点覆盖(最大匹配)
  • 最小支配集

支配集是一个点的集合,这些点与剩下的点之间都有边相连,点数最少的支配集叫最小支配集。
用处不大,可以来看一下这个题P2899 手机网络

  • 最小点覆盖

点覆盖是一个点的集合,使得所有边都至少有一端与是点集中的点,点数最少的点覆盖叫最小点覆盖。
二分图的最小点覆盖 = 最大匹配
就不给证明了,记住结论也没什么不妥,网上也有不少证明,还是一个理解性的问题。

  • 最小路径覆盖

这里的路径覆盖是指的DAGDAG的最小不相交路径覆盖,可相交路径覆盖需要用到传递闭包,不在此讨论。
最小路径覆盖就是用最少的路径条数,不重复不遗漏地覆盖一个有向无环图的所有顶点。

注意这里就不局限于二分图了。
它的解法:首先将原图中的每个点拆为xxx+nx+n,原图中的点在左侧,拆出来的大于nn的点在右侧,这样又形成了一个二分图。对于原图中的边(x,y)(x,y),在新建立的二分图中连边(x,y+n)(x,y+n),这样建出来的图叫拆点二分图。
最小路径覆盖 = 原图点数 – 拆点二分图的最大匹配
对这个定理的简单理解:将原图拆成二分图之后,每个点都是独立的一个路径,长度为00,每连一条边就会减少一条路径,连边的过程就是匹配的过程,所以要使路径最少,匹配就要最大。
洛谷P2764 最小路径覆盖问题 \rightarrow 题解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章