图的匹配
【概念】
都是无向图的概念
-
支配集:一个点集,使得无向图中每个点要么是点集中的点,要么与点集相邻。
-
独立集:一个点集,使得点集中任意两点不相邻。
以上两个在任意图中都是 NP 问题,也就是无法在多项式时间内求解的问题。
- 点覆盖:一个点集,使得所有边都至少与点集中一个点相连。
结论:点覆盖的补集是独立集,独立集的补集也是点覆盖。
证明:若点覆盖的补集里存在一条边连接,说明这条边没覆盖;而所有边肯定不可能两端都属于独立集,所以独立集的补集一定覆盖了所有边。
推论:最小点覆盖 \(\iff\) 最大独立集。
-
边覆盖:一个边集,使得所有点都有其中的邻边。(有孤立点则不存在边覆盖)
-
匹配:一些不重合的点对,点对之间有边。(注意有的点可能没有被选)
-
最大匹配:所有匹配中点对数量最多是多少
结论:最小边覆盖 = 最大匹配 \(k\;+ \;\)没有在匹配中选到的点的数量 \(n-2k\)。
证明(感性):最小边覆盖每次尽量选连接两个新点的边,这就是找最大匹配。
由这个结论,我们只要求出最大匹配,就能求出最小边覆盖。
【支配集(没啥用)】
- 图的结点分为支配集 \(U\) 与补集 \(V\),则 \(V\) 中点必然与 \(U\) 中某一个点相邻。
-
极小支配集:该支配集删除任意一个点,都不再是支配集。
-
最小支配集:点最少的支配集。
定理 \(\;\) \(U\) 为极小支配集,当且仅当对 \(U\) 中任意一个点 \(u\) 有如下条件,至少一个成立。
-
\(u\) 不与 \(U\) 中其他点相邻。
-
存在 \(v\in V\),使 \(u\) 是 \(v\) 的唯一 \(U\) 中邻点。
定理 \(\;\) 若无孤立点,极小支配集的补集也是支配集。
定理 \(\;\) 最小支配集大小 \(\le \dfrac{n}{2}\)。
【匹配】
- 选 \(k\) 对相邻的结点,无公共点。求最大的 \(k\)。
因为一般图匹配困难一些,先说二分图。
【二分图/二部图】
可以把 \(G=(V,E)\) 的 \(V\) 分成两个点集 \(A,B\),使 \(E\) 中的边两端都分属 \(A,B\) 的图。
二分图判定:染色法。
【二分图最大匹配】
- 无权,求最大匹配数。
法一:最大流 Dinic,\(O(m\sqrt n)\)。
Dinic 的缺点是难写、不容易做拓展;优点是快。
\(S\) 向左半边连 \(1\) 边,右半边向 \(T\) 连 \(1\) 边,左右之间的边流量都取 \(1\)。最大流就是最大匹配数。
为什么复杂度 \(O(m\sqrt n)\)?下面证明。(还没补)
-
先进行 \(O(\sqrt n)\) 轮找增广路。每轮 \(O(m)\)。共 \(O(m\sqrt n)\)。
为什么每次是 \(O(m)\)?这是因为边容量全是 \(1\),故每条边都只会在某增广路中贡献一次操作,所以总复杂度贡献是 \(O(m)\)。
-
再在残余网络上找增广路,每次增加 \(1\) 流量。我们要说明距离找完所有增广路,最多还需要 \(O(\sqrt n)\) 次,共 \(O(m\sqrt n)\)。
注意网络流里流了一条 \(A\rightarrow B\) 的边,就相当于匹配了这两个点。设我们此时 \(A,B\) 匹配了的边的集合是 \(P\),某最大匹配的匹配边集是 \(Q\)。
结论:\(P,Q\) 中的边形成了若干条锯齿状的路径。
(不可能有点的度 \(\ge 3\),否则抽屉原理在 \(P\) 或 \(Q\) 中存在一个点的度 \(\ge 2\),就不是匹配了)
下证:剩余的增广路 \(\le \sqrt n\) 条。
证明:因为已经做了 \(\sqrt n\) 轮 Dinic,所以剩下的增广路长度必然 \(\ge \sqrt n\) ……(待补)
法二:匈牙利算法,\(O(mn)\)。(不如 Dinic 呢 ~)
有一些概念:
-
交替路径:轮换经过匹配边/非匹配边的路径。
-
增广路:起止点都是非匹配点的交替路径。
依次访问 \(A\) 中点 \(i\),尝试对 \(i\) 找增广路。
-
成功找到增广路,则使增广路上所有边的匹配情况取反;
-
失败,则跳过。
bool srh(int x) {
for (int j = 0; j < e[x].size(); j++)
if (!vis[e[x][j]]) {
vis[e[x][j]] = true;
if (mc[e[x][j]] == -1 || srh(mc[e[x][j]])) {
mc[e[x][j]] = x, tw[x] = e[x][j];
return true;
}
}
return false;
}
这里面 \(mc[x]\) 表示 \(x\in B\) 当前的匹配点,\(tw[x]\) 表示 \(x\in A\) 当前的匹配点。如果是 \(-1\) 表示当前没匹配。
Q:为什么 if
后面不用 vis[e[x][j]] = false
?
A:因为它现在就找不到增广路,以后更找不到增广路,可以直接 vis = true
避免重复访问。
\(srh(x)\) 表示从 \(x\in A\) 出发,判断是否存在一条交替路径,如果存在,返回 true
并全部取反;否则返回 false
。
匈牙利算法的缺点是慢;优点是好写、容易拓展。(比如我们只用匹配到中间的结果就行了,可以用匈牙利算法)
【最小点覆盖】
有一种求最小点覆盖的方法:
网络流,建立超源点 \(S\),向每个 \(i\in A\) 连容量 \(1\) 的边;建立超汇点 \(T\),每个 \(i\in B\) 向 \(T\) 连容量为 \(1\) 的边;原本存在的边设置流量为 \(+\infty\)。
求最小割就是答案。因为对于每一条 \(+\infty\) 边,两端一定有被割掉的,所以就是一个点覆盖。
复杂度:\(O(m\sqrt n)\)。
【柯尼希定理】
二分图最小点覆盖 = 最大匹配。(无权)
所以可以直接求最大匹配,然后得到最小点覆盖,再 n - 最小点覆盖得到最大独立集。
【带权】
带权之后,最大匹配和最小点覆盖就不同了。但是最小点覆盖和最大独立集还是可以互相转化。
【带权二分图最小点覆盖】
最小点权和最小点数点覆盖
把网络流求最小点覆盖中,\(s\) 向左边连的边 以及 右边向 \(t\) 连的边 的容量 设为点权。
求最小割。
复杂度:上限 \(O(nm)\)。
如果有负权点:肯定是先把所有负权点选了,然后看每一条边有没有覆盖到。把所有没覆盖到的边用网络流做。
最大点权和最小点数点覆盖
把所有点权取反,就变成上一种情况了。
【二分图带权匹配】
先保证匹配最大,再保证权值。
有点权:把每条边的权设定为两端的点权之和,变成有边权的情况。
有边权:
-
费用流。中间的边的费用设定为边权,\(s\) 和 \(t\) 的边费用为 \(0\),容量和不带权的一样,跑最大/小费用最大流。
复杂度最差 \(O(n^2m)\),因为增广路长度最多 \(m\),所以最多分 \(m\) 次层;一轮增广 \(O(n)\);最大流 \(f\) 可以视为 \(n\)。
-
KM 算法:\(O(n^3)\)。但注意,KM 的 \(O(n^3)\) 经常跑满,有时候还没有费用流快。解决完美匹配问题。
对每个结点进行标号 \(lab\),使得 \(lab_u+lab_v\ge w(u,v)\)。(一定可以做到,因为可以赋值为无穷大)
\(lab_u+lab_v=w(u,v)\) 的边 \((u,v)\) 称为相等边或紧边。
当所有匹配边紧时,达到最大匹配。答案为 \(\sum lab\)。记原图为 \(G\),当前的紧边构成图 \(G'\)。
因为 \(\sum lab\ge \sum w\),故取相等时,\(\sum w\) 取最大。记左集为 \(U\),右集为 \(V\)。
-
首先 \(u\in U\),令 \(lab_u\) 为 \(u\) 邻边最大权;\(v\in V\),令 \(lab_v=0\)。
-
对于 \(u_1,u_2,\dots,u_n\in U\),依次:
-
若 \(u\) 在 \(G'\) 中未匹配,则从 \(u\) 出发搜 \(G'\) 的交错路并打标记。
-
判断有无增广路。
-
若有,增广结束(让 \(u\) 匹配上);无,调整 \(lab\)。怎么调整 \(lab\)?
记 \(x\) 为 \(U\) 中标记点,\(y\) 为 \(V\) 中无标记点,\(k\) 为 \(V\) 中标记点。(这里的标记是上面交错路标记)
不断重复这个过程,直到从 \(u\) 出发能找到一条增广路(直到从 \(u\) 出发能在 \(G'\) 中找到一个匹配的点):找到 \(lab_x+lab_y-w(x,y)\) 最小值 \(d\),然后对所有 \(lab_x-=d,lab_k+=d\)。显然这么做了之后,紧边仍然紧,而且至少让一条松边紧了。
-
-
【一般图最大匹配】
开花树算法(Blossom)
二分图当且仅当无奇环,开花树算法对奇环做了处理。
这里的“花”就是奇环。
因为奇环没法处理,直接把奇环缩点。原本连到奇环上的
原图存在增广路,当且仅当缩图存在增广路。
【题目】
稳定婚姻
教练曰:美国就变成一般图匹配,甚至自我匹配了。
就是二分图,注意夫妻之间没有连边。
初始让每个女人 \(i\) 的初始匹配都是男 \(i\)。然后枚举男 \(i\),尝试找增广路,如果找到了就不安全。
复杂度 \(O(nm)\)。
变换序列
简化题意:
定义 \(d(x,y)=\min(|x-y|,n-|x-y|)\)。要求构造一个字典序最小的长度 \(n\) 的序列 \(T_i\),使得 \(d(i,T_i)\) 刚好是给定的 \(d_i\)。(或者输出不存在)\(n\le 10^4\)。
我们构造一个二分图:若 \(d(i,x)=d_i\),则令 \(i\in A\) 向 \(x\in B\) 连一条边。问题就是求是否存在完美匹配。
显然当要求 \(d(i,x)=d_i\) 时,至多有两个 \(x\) 满足,所以复杂度可以接受。
但问题是:怎么保证字典序最小?
考虑一个中间结果:不妨假设此时 \((0,T_0=1),(1,T_1=2)\) 已经匹配好了,且是最小的使得后面能匹配的匹配。
因为 \(T_0,T_1\) 已经确定,后面改了肯定不优,我们直接锁定 \(T_0,T_1\),后面干什么都不能动。
接下来考虑尽量让 \(T_2\) 小。令 \(T_2\) 尝试匹配尽可能小的,记作 \(t\)。此时我们只需要检查哪个原本匹配 \(t\) 的 失配了,是否还能找到增广路,就能判断 \(T_2\) 能否可以 \(=t\)。
如果真的匹配上了,因为字典序是贪心的,直接将 \(T_2\) 锁定为 \(t\)。
当然如果 \(T_2\) 配不了 \(t\),就检查 \(t\) 更大的。
整个算法流程:先跑一个二分图匹配,然后挨个尝试变小。
复杂度是多少?
对于每个点,我们会从小到大枚举它所有邻边,尝试让那个失配的点找增广路。上面说了,一个点最多两条边,而找增广路是 \(O(m)\) 的,所以对于一个点是 \(O(m)\) 的,在这题里,也就是 \(O(2n)=O(n)\) 的。
所以总复杂度是 \(O(n^2)\) 的,当然这只是理论上限,实际上根本跑不满。
小行星
建立一个二分图:左右各 \(n\) 个点,分别表示 \(n\) 行 \(n\) 列。对于一个小行星 \((x,y)\),则左边 \(x\) 和右边 \(y\) 之间连边。然后求最小点覆盖(最大匹配)即可。
因为左边 \(x\) 和右边 \(y\) 连边,就要求了 \(x,y\) 中必须选一个,对应了一颗小行星要么被行消除要么被列消除。
线段
把横向、纵向的线段作为二分图的左右两边。有交点的线段相互连边。
求最大独立集 = n - 最小点覆盖 = n - 最大匹配。
骑士共存问题
把每个格子抽象为结点,可以相互攻击的结点连边。
为什么是二分图?因为国际象棋棋盘黑白染色。
然后求最大独立集。
考虑用染色方法构建二分图。
长脖子鹿放置
染色方法(证明是二分图的方法):一行一种颜色。
方格取数问题
每个格子抽象为结点,相邻格子代表的结点连边,点权是格子上的数。求最大点权和独立集。
用 sum - 最小点权和点覆盖 求。
太空飞行计划
左半边点代表实验,右半边点代表仪器。
\(s\) 向左半边点连边,容量为这个实验的收益。
右半边点向 \(t\) 连边,容量为这个仪器的花费。
一个实验 \(u\) 向它所需的所有仪器连边,容量为 \(+\infty\)。
考虑最小割,对于一个到 \(s\)(或 \(t\)) 的边被割的点:
-
若是代表实验的点,代表不做这个实验。
-
若是代表仪器的点,代表买这个仪器。
每个边割了,都是负收益。
这么做的意义是什么:对于一条 \(+\infty\) 边,连 \((i,j)\) 两点:代表要么不做实验 \(i\),要么买仪器 \(j\)。
然后用所有实验的总收益减去最小割。
怎么理解?对于实验 \(i\) 和仪器 \(j\),只有(要做 \(i\) 但是不买 \(j\))这一种情况是矛盾的,于是用 \(+\infty\) 的边代表这个矛盾。
最后的问题:怎么求最小割?
注意不能检查每条边的容量,因为最大流流过去,一条增广路上随便选一条边都有可能。
设最小割为 \(C\),枚举每一个点,先把它到 \(s/t\) 的容量变成 \(0\),跑最小割。看一下最小割是否是 \(C-w\):如果是,则必存在一个最小割方案,删除了这个点;如果更大,则恢复这条边到原来的容量。
复杂度 \(O(nm\times n)\)。
Card Game
二分等级。
每张卡片抽象为一个结点,魔力值和为质数的卡片之间连边。
尝试让二分图的左右两边代表魔力值为奇/偶的卡片。如果是“和不能为奇质数”,就是二分图;但可惜现在不是。
如果和为 \(2\),一定是 \(1+1\),我们尝试特判这种情况:所有 \(1\) 魔力值的结点只留一个能量最大的。
然后构建二分图,点权是卡片的能量,求最大权独立集。