Hall 定理
事发原因:最近和学弟随机聊天,记录一下哇,欢迎大家提出建议/指正。
众所周知 Hall 定理一般用于解决二分图完美匹配的存在性问题,实际上它还能给出匹配数,并在加强条件后得到各种变体。
Hall 定理
这个是图匹配的定理,说有一个二部图 \(G = (X,Y,E)\),我们想知道:
- \(X\)-完美匹配:是否存在一个匹配,使得 \(X\) 中每个点都成为匹配点。
- 怎么用 Hall 定理计算最大匹配。
首先考虑解决第一个问题,我们有一个简单的观察,这个性质是必要的:
- 我们用 \(Y(x)\) 表示左部点集 \(x\) 在右部点中的所有邻居。
- 对于 \(X\) 的任意子集 \(x\),必须满足 \(|Y(x)| \ge |x|\)。否则右部点不够多,肯定无法 \(X\)-完美匹配。
- Hall 定理指出,在考察所有子集后,已经充分必要(可以归纳证明,需要一些讨论,这里略)
推论 1 如果存在 \(X\)-完美匹配,\(Y\)-完美匹配,那么存在完美匹配。
推论 2 如果存在 \(x\)-完美匹配,\(y\)-完美匹配,那么存在一个匹配,同时覆盖 \(x,y\)。
由于前者是后者的特殊情况,只需证明后者可以构造,具体方法和 Berge 引理的证明方法一样。
推论 3 正则二分图(所有点度数均为 \(k\))必然有完美匹配。
考虑每个子集 \(x\),向右发射 \(k|x|\) 个度数,由鸽巢原理有 \(k|x| \le k|Y(x)|\),同时消去 \(k\) 即得证。
Hall 定理的 Deficiency 形式
对于一个不满足 Hall 条件的的子集 \(x\),我们计算 \(d(x) = |x| - |Y(x)|\),这表明其中 至少 有 \(d(x)\) 个点无法被匹配。
Hall 定理的 Deficiency 形式指出:
等式左侧表示集合 \(X\) 里未能匹配的顶点数,右侧则表示最大的 Deficiency,这样移项后就能解决前文的第二个问题。
一个等价的说法是:如果最后 \(X\) 中有至少 \(d\) 个节点无法被匹配,则对于任意 \(x \subseteq X\),都有 \(|x| \le |Y(x)| + d\)。
基本形式解决了判定性问题,而这一形式则进一步给出了具体的匹配数。
必要性:对任何子集,未匹配的点 \(\overline{x}\) 不超过 \(d\) 个,且其中匹配的点数 \(|x'| \le |Y(x)|\),故有 \(|x| = |x'| + |\overline{x}| \le |Y(x)| + d\) 成立。
充分性:构造地,新增 \(d\) 个右部点,连向所有左部点,此时根据原始 Hall 定理必然得到一个 \(X\)-完美匹配,随后删掉与新增点的匹配。
匹配覆盖 matching covered
一张连通图是匹配覆盖的,当且仅当每条边都能属于一个完美匹配。
对于二部图,普通 Hall 定理给出了 \(\forall x \subseteq X, |Y(x)| \ge |x|\)。
实际上,我们可以证明,当 \(|X|=|Y|\) 时,强化条件 \(\forall x \subsetneq X, |Y(x)| \gt |x|\) 等价于连通二分图是匹配覆盖的。
Proof
注意如果原图不连通,那么只要分开考虑每个连通块。
充分性(强化条件 \(\implies\) 匹配覆盖)
对于任意一条边 \(e = (u, v)\) 我们在匹配中强行选择它,此时需证明去掉两个点的新图 \(G' = G - \{u,v\}\) 具有完美匹配。
不妨验证 \(G'\) 满足 Hall 定理:两部点各被删去了一个点,故每个 \(|Y(x)|\) 至多减一,于是满足。
必要性
我们需要证明对于一个匹配覆盖图,不存在一个子集 \(x\) 使得 \(|x| = |Y(x)|\)。
假设存在这样一个子集,那么 \(x\) 里的点必然要与对面的 \(Y(x)\) 一一匹配:
- 由于原图连通,由 \(x\) 和 \(Y(x)\) 构成的导出子图必然通过至少一条边 \((u,v)\) 与外部连通。
- 如果存在完美匹配覆盖 \((u,v)\),那么必然导致 \(x\) 无法与 \(Y(x)\) 一一匹配。
- 故不成立,反证完成。
广义 Hall 定理
见例题 1.
例题
25 ICPC Online 2 - C
有 \(3\) 个人 \(a,b,c\),以及 \(7\) 类题目,分别有 \(F_a, F_b, F_{ab}, \dots F_{abc}\) 题,共 \(S\) 题。
每类题只能分给下标中的人做。每道题只能分给一个人做。
请最大化 \(\min \{ t_1,t_2,t_3 \}\) 的值,这里 \(t_i\) 表示第 \(i\) 个人的做题数。
Solution
我们考虑构造二分图:
- 如果想要 \(a,b,c\) 每人至少做 \(k\) 题,可以为每人生成 \(k\) 个点,所以左侧总共有 \(3k\) 个节点。
- 右侧是所有题目,共 \(S\) 题。
- 如果一个题可以被某个人做,则与那个人的 \(k\) 个点连边。
问题转化成:是否存在一个能完全覆盖左侧 \(X\) 的匹配?我们考察每个子集,举部分例子:
- 大小为 1 的
a满足 \(k \le F_a + F_{ab} + F_{ac} + F_{abc}\) - 大小为 2 的
ab满足 \(2k \le F_a + F_{ab} + F_{ac} + F_{abc} + F_{b} + F_{bc}\) - 大小为 3 的
abc满足 \(3k \le S\)
这样对所有限制取最小值,就得到了最大的合法的 \(k\)。使用 Deficiency 形式可以得到一样的结果。
P.S. 其实我在赛时是按鸽巢原理做的,也有网络流等八仙过海做法。
广义霍尔定理
这个题的做法,也给出了广义霍尔定理,考虑如下二分图形式的网络流(连边没有限制):
如果左部能满流,当且仅当对于每个子集 \(x\),都有 \(\sum_{i \in x} a_i \le \sum_{i \in Y(x)} b_i\)
ai INF bi
x1 y1
S -> x2 --> y2 -> T
x3
在这道题目中,\(a_i\) 均为 \(k\),而 \(b_i\) 是每套题的数量。对于广义定理的证明是构造的,即本题的解法。
CF1009G Allowed Letters
字符集大小 \(|\sum|\) 为 \(6\),给定了一个长度为 \(n \le 10^5\) 的字符串 \(S\)。
部分下标被限制了只能放某些字符。你需要重排这个字符串,使其字典序最小,或者报告无解。
首先有一个很暴力的 \(O(6n \cdot n \sqrt n)\) 做法,每次尝试贪心放一个字符,然后用 HK 或 Dinic 跑最大匹配,看剩下来的情况是否合法。
不过由于字符集很小,我们可以转为使用广义 Hall 定理判断:
- 左部点为 6 种字符,流量为剩余可使用的数量。
- 右部点为每个位置,向可使用的字符连边,流量为 1。
预处理后缀的右部点情况,每次枚举左部子集即可判断是否合法。复杂度为 \(O(6n \cdot 2^6 )\),可以通过。
判断 matching covered
给定一张二分图,无重边,保证连通,判断它是否是匹配覆盖的,\(n \le 10^5\)。
如果没有完美匹配,那么输出 No。
否则可以用 HK / Dinic 在 \(O(n \sqrt n)\) 时间内求出一个完美匹配,我们建立新图 \(G\):
- 原图上在完美匹配中的边 (x, y),连 \(x \to y\);
- 原图上不在完美匹配中的边,连 \(y \to x\)。
如果该图 \(G\) 只有一个强连通分量,那么输出 Yes,否则输出 No。
Lemma 1: 两个完美匹配的对称差(\(M \oplus M'\))必然由若干个交错环组成(因为度数只能是 0 或 2)。
因此边 \(e\) 属于某个完美匹配,等价于它在有向图 \(G\) 中属于某个有向环。
Lemma 2:二分图上的环均为偶环(显然耶)。
因此图 \(G\) 可以被分解成若干个偶环的并,每条边都能被有向环覆盖,证明了这张图必然是一个 SCC。
Latin Rectangles
对于 \(r \times n\) 的矩阵(\(r \lt n\)),规定只能填入 \(1 \sim n\) 的元素,且每行、每列都不能出现重复数字。
试证明总是可以新增一行,扩展为 \(r+1\) 行(\(r + 1 \le n\))。
左部点代表每列,右部点为每个数字,如果两者不冲突,则连一条边。
由于已经放了 \(r\) 行,故左部点每个点度数为 \(n-r\),而每个数字也只有 \(n-r\) 列可放。
故这样的二分图总是正则图,根据前文的推论 3,必然具有完美匹配。
[CERC2016] Bipartite Blanket
给定一个左右各有 \(n,m\) 个点(\(n,m \le 20\))的二分图,每个点都有一个权值。一个顶点集合是合法的,当且仅当满足两个条件:
- 这个顶点集合的总权值大于等于常数 \(t\)。
- 这个顶点集合能被某一个匹配完全覆盖。
需要统计有多少合法的集合。
根据 Hall 定理,我们可以在 \(O(2^n)\) 里简单枚举 \(x \subseteq X\),来判断 \(X\) 是否具有 \(X\)-完美匹配。
但如果需要对每个 \(x \subset X\) 的导出子图都求解呢?直接枚举子集是 \(O(n 3^n)\),而使用高维前缀和可以做到 \(O(n 2^n)\)。
int f[1 << n]; // 提前暴力枚举,求出每个集合 x 本身是否满足
for (int i = 0; i < (1 << n); i++) {
for (int j = 0; j < n; j++) {
if (i & (1 << j)) f[i] &= f[i ^ (1 << j)];
}
}
我们对两侧的集合分别求出合法的 \(f,g\),并记录每个子集的价值,随后对价值排序。
那么对于一个 \(f\),使得总价值超过 \(t\) 的 \(g\) 一定是一个后缀,可以单调指针求解 \(O(n2^n + m2^m)\)。
这里的正确性使用了之前的推论 2,也就是说如果两侧的子集 \(x,y\) 分别合法,那么一定存在一个匹配同时覆盖它们。

浙公网安备 33010602011771号