Gale-Ryser 定理
前情提要:不知道为什么在写这种东西,但看起来是经典问题,总之先学了。感觉写得一坨,欢迎大家讨论/指正!
经典问题(可二分图序列)
给定 \(n,m\) 表示二部图两侧的点数。再给出 \(A = (a_1, a_2 \dots a_n)\),\(B = (b_1, b_2 \dots b_m)\) 表示每个点的度数。
请判断是否有一个合法的二分图与之对应,如有请构造一个解。保证 $ 1 \le n,m, \sum a, \sum b \le 10^5$。
首先我们可以对 \(a_i\) 和 \(b_i\) 从大到小排序。然后有一个显然正确的贪心策略:
- 对于度数目前最大的点 \(a_1\),必须与右侧的 \(a_1\) 个不同的点相连,故优先考虑。
- 我们把度数尽可能大的 \(b_i\) 分配给它(每个都 -1),这样可以留下更多不同的点。
也就是说我们用优先队列维护 \(B\),每次取出前 \(a_i\) 大的 \(b\) 并且减一后放回去,最后要求优先队列中全为 \(0\)(两部度数相等)。
这样复杂度是 \(O(S \log n)\),\(S = \sum a_i = \sum b_i\),并且构造出了解。把优先队列换成桶可以做到 \(O(S)\)。
实际上构造解的复杂度下界就是 \(O(S)\),因为真的有 \(S\) 条边,我们后文会做到 \(O(n+m)\) 判断是否有解。
其实对这种做法 \(a_i\) 是可以乱序的,只要保证每次选的是最大的若干个 \(b\) 即可,这个可以用交换法说明:
交换法 / 归纳法
假设 \(a_1 \lt a_2\) 与 \(b_1 \gt b_2\) 且 \(a_1\) 选了 \(b_1\) 而 \(a_2\) 选了 \(b_2\)。
b_1 b_2
a1 1 0
a2 0 1
我们总是可以交换这两个选法,使得 \(a_2\) 选到更大的 \(b_1\),并且这样的操作不改变行、列的加和/度数。
根据策略,乱序处理 \(a_i\) 时,我们依然是让它先占用大的,故可以之后再进行交换操作(或不进行),正确性可以归纳:
- 考虑我们的策略贪心了前 \(c\) 个 \(a_i\) 后,不论怎么排列前 \(c\) 个元素,最后得到的剩余度数序列 \(B'\) 总是一样的;
- 类似的归纳方法还出现在 joisc2016 回転寿司,不过和本文没啥关系。
Gale–Ryser theorem
类似 Hall 定理,对于任何左部点 \(X\) 的子集 \(S\),我们考虑这样的一个必要条件:
解释一下右侧的含义:每个右部点 \(b_i\) 至多可以接受左部的 \(\min(b_i, |S|)\) 条边。
Gale–Ryser 定理说,考察每个子集后,已经充分必要。但还可以改进!
不妨固定 \(|S|\) 的大小,我们发现右侧的值总是固定,而左侧最严格的限制,只需要考察最大的 \(|S|\) 个 \(a_i\)!
因此,盖尔-赖泽定理(Gale–Ryser theorem):度数序列可构成二分图,当且仅当在对 \(A\) 排序后,对于任意 \(1 \le k \le n\),均满足
此外还需要满足一个平凡的前提 \(\sum a = \sum b\),即两部的度数一样,我们后文最好默认这一点。
等价形式 1
注:这也是 Gale 定理最好用的形式,非常强大。
构造共轭序列 \(C=(c_1, c_2, \dots c_n)\),其中 \(c_i\) 表示在 \(B\) 中有多少元素大于等于 \(i\)。
盖尔-赖泽定理(Gale–Ryser theorem):这种二部图存在的充要条件是,序列 \(A\) 被 \(C\) 支配(Majorization):
同样地,表示左部度数最大的前 \(k\) 个度数之和,不能超过右部能提供的最大容量。
因此在排序 \(a_i\) 并预处理 \(c_i\)后,可以在 \(O(n)\) 的时间内完成判定,只需要判定的情况下比贪心构造的 \(O(S)\) 牛多了。
相较于原始形式,这一形式(某种程度上)降低了计算右部点限制的复杂度,是第一个强大之处。
根据定义,我们的 \(c_i\) 是不升的,那么前缀和 \(f(k) = \sum^k_{i=1} c_i\) 总是一个上凸的函数。
可以预见,如果不等式的左侧 \(\sum^k_{i=1} a_i\) 也有一定的性质,我们有机会更快地检查这些限制,是第二个强大之处!
小优化
我们只需要考虑 \(k = n\) 以及满足 \(a_k \gt a_{k+1}\) 的 \(k\),即可以跳过值相同的段。
因为不等式右侧是上凸的,而左侧每次增加一个相同值,是在局部用固定正斜率的线段去判断与凸包是否有交。
这样一来,只有 \(O(\sqrt {S}), S = \sum a_i\) 个限制需要检查,不过这个优化可能并不实用。
证明
我们先说明为什么两个形式是等价的,然后利用网络流证明原命题的正确性,注意网络流的刻画在一些题目中是有用的。
Lemma 1. 发现我们的 \(C\) 其实就是 \(B\) 的共轭 Ferrers 图(就是杨表/分拆数里的那个),没有前置知识也不要紧,这里举个例子:
3 2 2 1
1 ■
3 ■ ■ ■
4 ■ ■ ■ ■
横着看是 \(B=(3,2,2,1)\),竖着看就是 \(C=(4,3,1)\),并且 sum 一样。所以对于任意常数 \(k\),总是有:
意思是把高于 \(k\) 的柱子删到只有 \(k\)(只保留最下面 \(k\) 行),然后横着考察最下面 \(k\) 行,这个正确性显然。
接下来开始正式证明 Gale 定理,我们考虑这种网络流做法:
- \(S\) 向 \(x_i\) 连边,容量为 \(a_i\)。
- 中间连 \(nm\) 条边,容量为 \(1\)。
- \(y_i\) 向 \(T\) 连边,容量为 \(b_i\)。
对于其上的一个最小割,将图分为 \((U,V)\) 两个部分,称 \(U\) 中的左、右部点分别为 \(I, J\),并称 \(|I| = k\),那么这个割的容量为:
我们现在固定 \(I\)(对于每个 \(I\) 单独考虑),我们要怎么分配右部点呢?
- 放在 \(U\) 里会造成 \(b_j\) 的贡献。
- 放在 \(V\) 里会造成 \(k\) 的贡献。
由于是最小割,可以发现策略居然固定,我们总是取最小的,可以将容量化简为:
为了保证最小割至少是 \(S = \sum a\),有不等式:
两侧删掉一样的部分,移项:
现在我们证明了:可二分图化等价于,任意大小为 \(k\) 的 \(I\) 都必须满足这个条件。于是对 \(a\) 从大到小排序后,可以得到下面的式子。
这是因为只要最大的 \(k\) 个满足,其余大小为 \(k\) 的集合一定也满足,得证。
Gale 是 Hall 吗?
前面我们说,对于 \(X\) 的任意子集 \(S\),要满足:
这乍一看似乎是 Hall 定理,可能会想到把 \(a_i,b_i\) 拆成这么多个点,但这种情况下会导致 \(a \to b\) 出现重边,所以具体表述应该是:
- 左侧的 \(k\) 个顶点需要向右侧连出 \(\sum a_i\) 条边。
- 右侧的每个点 \(i\),只能接受 \(\min(b_i, k)\) 条边。
同样是选取了一个必要条件,在考察所有子集后变得充分,可以说这两个定理的动机(极小极大对偶)几乎是一样的。
我姑且认为这个还是得叫 Gale 定理,而不能是 Hall 定理,不知道读者有没有意见,也许大力构造一下就可以说明是等价的,欢迎来讨论耶耶。
等价形式 2
这个比较平凡。
设 \(p\) 和 \(q\) 为 正整数的划分,当且仅当 \(q\) 被 \(p^*\) 支配时,存在一个 01 矩阵 \(A\) 使得 \(c(A)=p, r(A)=q\)。
也就是说我们可以将二分图的连边放在 01 矩阵上刻画。行和、列和,分别对应了左右部点的度数。
也可以反过来看,可能题目给出了关于 01 矩阵的信息,将它反过来视作是二分图。
例题
[awc0031_d] - Library Inventory Check
有 \(n\) 天与 \(m\) 本书,每天至多检查 \(L_i\) 本不同的书,每本书需要被检查 \(R_i\) 次。
只需要回答 Yes / No 表示是否存在合法方案。\(1 \le n,m \le 10^5\)。
这题的区别在于,我们每天不需要看满 \(L\) 本,容易想到让这个作为前文 \(B\) 的部分。
于是只需要在排序后,检查是否满足 \(\forall k \in [1,n]\),\(\sum_{i=1}^k R_i \le \sum_{i=1}^k \min(L_i,k)\)。
意思是说,由于 A, B 在定理中的地位是对称的,往往将更宽松的作为 B(需要检查的限制)是有利的。
不是题
给定长度为 \(N\) 的序列 \(A,B\),每次操作可以选恰 \(M\) 个 \(a_i\) 加一。在同一次操作中,同一个元素不能被反复选。
问 \(B\) 是不是从 \(A\) 通过若干次操作得到的。
考虑将每次操作作为右部点,则度数均为 \(M\)(非常特殊!)。同时令 \(x_i = b_i - a_i\) 作为左部点。
此时根据 Gale 定理,设一共进行了 \(K\) 次操作,操作方案存在的充要条件为:
- \(\sum x_i = KM\)
- \(x_{\max} \le K\)
条件 2 大家可以仔细理解一下。不难发现 Gale 定理对于处理形如本题的操作,有非常强大的功能。
[POI 2015 R2] Logistics
维护一个长度为 \(n\) 的序列,一开始都是 \(0\),有 \(q\) 次操作:
- 单点修改 \(a_i\) 的值
- 询问能不能重复 \(s\) 次操作:每次在这个序列上选出 \(c\) 个正数,将它们减去 \(1\)(不修改序列)
\(1 \le n, q \le 10^6\),\(0 \le a_i, s \le 10^9\)
即每次询问,要求左部 \(s\) 个点的度数恰好都是 \(c\),右部点度数则不超过 \(a_i\),是否可行。
众所周知,结论是判断是否有 \(c \cdot s \le \sum_1^n \min(a_i, s)\),右侧可以用数据结构维护,求出 \(a_i \le s\) 之和,以及有多少大于 \(s\) 的数。
然而我们的 Gale 定理是要求对每个 \(k \cdot s\) 都要考察的,到底怎么变成只考察 \(c \cdot s\)的呢?
上式右侧可以改写成共轭序列 \(A^*\) 的形式,由于 \(a^*_i\) 的值单调不升,其前缀和 \(f\) 总是一个上凸的函数。
要考察是否总有 \(\forall k \in [1, c]\),\(f(k) \ge ks\),只需要考察 \(f(c)\) 处是否满足即可!
如果读者未能理解,还可以看下面另一种证明方法。
换个角度
我们刚刚对右部点使用了共轭序列,这次换成对左边使用,也可以说明正确性!
- 最后右部点使用了的度数,构成降序序列 \(D = \{d_1,d_2, \dots d_n\}\)
- 左部点的共轭序列 \(B^* = [s,s, \dots s,s,0,0,0 \dots]\)
当 \(1 \le k \le c\) 时:不等式右侧总是 \(ks\),而每个 \(d_i\) 至多只能够连到 \(s\) 个点,故总是成立。
当 \(c < k \le n\) 时:不等式右侧总是 \(cs\),而左侧变为 \(\sum^k d_i\),只需要考察最大的情况即可。
这里也可以看出共轭序列的重要性,大大简化了讨论难度(很难在动态 \(k\) 时通用地讨论 \(\sum \min(d,k)\) 的值)。
[abc143_f] Distinct Numbers
给定 \(n\) 个数 \(a_i\),你需要建立尽可能多的组,满足每组大小恰为 \(k\),且组内元素的值不重复。
分别对 \(k = 1, 2 \dots n\) 回答,最多能得到多少组。\(1 \le a_i \le N \le 3 \times 10^5\)。
简单的习题,注意我们学了 Gale 定理!我们的做法最好是线性的。
UVA 12382 Grid of Lamps
有一个 \(n \cdot m\) 的 01 矩阵对你隐藏,你只知道每行有至少 \(a_i\) 个 \(1\),每列至少有 \(b_i\) 个 \(1\)。
请确定 至少 有多少个 \(1\)。保证 \(1 \le n,m \le 1000\)。
用本文开篇提到的构造方法贪心即可,最后没被减完的都会变成对答案的增量,然而这样复杂度是 \(\tilde O(nm)\) 的。
我们伟大的 Galgame Gale 定理怎么会容许这样的事发生?难道数据范围不能改成 \(10^5\) 吗?
不妨这样考虑,最小化 1,就是最大化 0,我们对 0 的数量求最大流(最小割)即可:
对于这个式子,如果读者没有看最上面对 Gale 定理的证明可能会感到困惑,回忆 Gale 定理给出的最小割,在固定 \(I\) 时是这样的:
我们对 \(a_i' = m - a_i\) 从小到大排序,然后再用共轭的形式维护第二个求和号,答案就是 \(nm - \text{flow}\)。
我认为第二种做法对理解 Gale 定理的帮助比较大,而且确实有一种 Hall 定理的风味。
最重要的是复杂度优秀,是线性 \(O(n+m)\) 的,排序可以换成桶排做到严格线性,参考代码。
XXI Open Cup, Grand Prix of Korea - Advertisement Matching
有 \(n\) 种广告,每种要被发给 \(a_i\) 个用户。有 \(m\) 个人,每人可以看不超过 \(b_i\) 个不同的广告。
有 \(q\) 次修改,每次使得一个 \(a_i\) 或 \(b_i\) 加减一。
每次修改后回答,是否可以将所有广告都发出去。保证 \(1 \le n,m,q \le 10^5\)。
不带修的话非常简单,带修的时候,由于 \(\sum_{i=1}^k \min(b_i,k)\) 对每个 \(k\) 都要修改,有点难受,我们使用共轭的表述:
- 要求对于 \(1 \le k \le n\) 都有 \(\sum_{i=1}^k (c_i - a_i)\) 非负。
由于每次只会加减 1,对于 \(b_i\) 的修改来说,只会改变一个 \(c_i\) 的值,可以在线段树上完成对后缀的修改和检查。
Gale 定理希望 \(a_i\) 是排序后的,由于加减 1,可以认为整体排序都不变,只有相邻两处交换了,也容易修改和检查。
某天梦到的题 1(不是题)
给定度数序列 \(A=(a_1,a_2 \dots a_n)\),问有多少长度恰为 \(m\) 的无序度数序列 \(B\) 满足 \((A,B)\) 可二分图化。
注意这里的 \(B\) 是无序的。满足 \(1 \le n,m \le 100\),\(\sum a_i \le 5000\)。
由于 \(B\) 未知而 \(A\) 已知,我们对 \(A\) 求共轭序列 \(C\),并且求出共轭序列的前缀和 \(P\)。
问题转化为,有多少 \(B=(b_1 \ge b2 \ge \dots b_n \ge 0)\) 满足:
- \(\sum b = \sum a\),两侧度数一样。
- 对于所有 \(1 \le k \le m\),都有 \(\sum_{i=1}^k b_i \le P_k\)。
首先 \(f[i][j][s]\) 表示确定前 \(i\) 个元素,第 \(i\) 个值为 \(j\),目前总和为 \(s\) 的方案数,有下面的转移(如果 \(s\) 大于 \(P_i\) 则为 0)
这样是 \(O(m \cdot n^2 S)\) 的,考虑后缀优化,设 \(g[j][s] = \sum_{k=j}^n f[i-1][k][s]\),那么有:
这样是 \(O(nm S)\) 的。
CF1740F Conditional Mix
给定了 \(n \le 2000\) 个大小为 \(1\) 的集合 \(\{ a_i \}\),每次操作,选择两个没有公共元素的集合,合并它们。
在进行任意次操作后,得到了若干集合,将这些集合的大小作为可重集 \(M\),请问有多少种不同的 \(M\)。
因为一开始都是单元集,所以所有的合法情况都能合并出来。
考虑将每种数字 \(x\) 作为左部点,把集合作为右部点。如果数字 \(x\) 共出现了 \(c_x\) 次,需要连向右部中 \(c_x\) 个点。
问题转化为给定每个左部点的度数 \(c_x\),需要统计点数为 \(m = 1, 2, \dots n\) 的右部点的方案数,即前面那个题,但还有一些优化:
依然 \(f[i][j][s]\) 表示确定前 \(i\) 个元素,第 \(i\) 个值为 \(j\),目前总和为 \(s\) 的方案数。
但是这里注意到,因为全局总和 \(n\) 满足 \(i \times j \le n\),所以前两维只有 \(O(n \log n)\) 种状态。
于是套用前面的做法,复杂度为 \(O(n^2 \log n)\)。本题这里用度数刻画了集合大小。
[JOIST 2023] 曲奇 / Cookies
有 \(n\) 种饼干,每种有 \(a_i\) 个。给定了 \(m\) 种盒子,大小是 \(b_i\),数量无限。
你需要判断是否能选出一些盒子,使得所有饼干都被放进去,每个盒子都恰好放满,且盒内饼干种类不同。
如果可以的话,请最小化盒子数量,并输出一个方案。
\(1 \le n, \sum a \le 15000\)
前面的题目在 dp 时可以任选度数 \(j\),而这里限制只能选部分度数 \(j = b_i\),实际上没有本质区别。
套用前面做法,依然是 \(O(n^2 \log n)\),但这里只在乎是否合法,于是还可以压位,有点细节呃呃。
注意我们维护了 \(f[i][j][s]\) 其中 \(j\) 表示这个位置放了 \(j\) 的盒子,所以反着找方案是很方便的。
现在知道了每个盒子的大小,用本文一开始的贪心算法构造一组解就行。
[ARC169D] Add to Make a Permutation
给定一个长度为 $N \leq 250000 $ 的整数序列 \(A=(A_1,A_2,\cdots,A_N)\)。\(A\) 的每个元素都是 \(0\) 到 \(N-1\) 之间的整数。
你可以进行如下操作任意次(包括 \(0\) 次):
- 从 \(A\) 中恰好选出 \(M\) 个元素,将选中的每个元素的值加 \(1\)。
- 如果加 \(1\) 后某个元素的值变成了 \(N\),则将其值变为 \(0\),即在模 \(N\) 意义下进行。
你的目标是将 \(A\) 变成 $ (0,1,\cdots,N-1) $ 的一个排列。请判断目标是否可以达成,如果可以,输出所需的最小操作次数;否则输出 \(-1\)。
比较难的习题,在某些步骤使用了 Gale 定理,而其他环节需要很多的观察。
其他
嗨嗨,小伙伴们,你们认为这个定理应该叫 Galgame 定理,还是珈乐定理呢?

浙公网安备 33010602011771号