Erdős-Gallai 定理

前情提要:不知道为什么在写这种东西,但看起来是经典问题,总之先学了。感觉写得一坨,欢迎大家讨论/指正!

推荐先阅读 Gale-Ryser 定理,本文定理是它在一般无向图上的推广。

本文除了介绍 Erdős-Gallai 定理(无向图),还会介绍 Fulkerson-Chen-Anstee 定理(有向图),原理是一样的。

经典问题(可无向图化序列)

给定 \(n\) 个点的度数 \(d_i\),请回答是否有一张无向图与之对应,如有请构造一个。

\(1 \le n, \sum d_i \le 10^5\)

首先有一个比较显然的贪心做法,我们将 \(d_i\) 从大到小排序,然后

  • 每次取出目前度数最大的点 \((x, d_x)\)
  • 对于余下的点,取度数最大的 \(d_x\) 个点,使得它们度数减一,与 \(x\) 相连。
  • 重复这个步骤,若取不出足够多的点/出现负数则无解,若最后全为 0 则有解,并构造出了解。

这样做的正确性显然,因为度数为 \(d_x\) 的点必须与 \(d_x\) 个点相连,我们的贪心策略会留下尽可能多的点。

这个贪心算法可以简单地用优先队列完成,或者在排序后利用差分完成。复杂度为 \(\tilde O(n + \sum d)\)
如果读者提前学习了 Gale-Ryser 定理,会发现两者提供的贪心算法是一样的,同时本算法要求度数从大到小排序。

注:本节算法的大名叫 Havel-Hakimi 定理(哈韦尔-哈基米定理),哈基米真名解放了,咔咔。

Erdős-Gallai 定理

前文的做法在需要构造方案时已经足够优秀,但如果只需要判定呢?首先要求总度数是偶数,接下来:

类似 Hall 定理、Gale-Ryser 定理,对于任何顶点 \(V\) 的一个子集 \(S\),我们考虑这样的一个必要条件:

\[\sum_{i \in S} d_i \le |S|(|S|-1) + \sum_{i \notin S} \min(d_i, |S|) \]

  • 取顶点 \(V\) 的任意一个子集 \(S\),其总度数为 \(\sum_{i \in S} d_i\),即不等式左侧。
  • 这个子集内部至多可以解决 \(|S|(|S|-1)\) 个度数(完全图),其余的必须由外部顶点提供。
  • 每个外部的顶点,至多可以提供 \(\min(d_i, |S|)\) 个度数。

注:与 Gale-Ryser 定理的区别仅在于,二分图内部不能连边,而一般图这里多了完全图的度数。

Erdős-Gallai 定理说,考察每个子集后,已经充分必要。但还可以改进!
不妨固定 \(|S|\) 的大小,此时左侧最大值在度数最大的 \(|S|\)\(d\) 处取到,而右侧最小值在度数最小的 \(|V| -|S|\)\(d\) 处取到,可以同时满足!

于是我们对 \(d\) 从大到小排序后,只需要对 \(1 \le k \le n\) 考察:

\[\sum_{i=1}^k d_i \le k(k-1) + \sum_{i=k+1}^n \min(d_i, k) \]

这样的话,我们就得到了一个 \(\tilde O(n)\) 的算法!可以在线性时间里直接维护右侧,但是我们并不需要这么干,请阅读下一节。

注:这个定理的证明比较困难,不能直接用 \(S-T\) 网络流说明,建议不考虑证明。

直接维护右侧(可跳过)

这里教大家怎么线性地维护右边那坨东西。

我们画出 \(d_i\) 的 Ferrers 图,如下图是 \(D = (3,2,2,1)\) 的一个例子。
这里 \(\min(d_i, k)\) 表示只看最下面 \(k\) 行,相当于不等式右侧变成了询问一个后缀矩形范围里的点数。

     3  2  2  1
1    ■
3    ■  ■  ■
4    ■  ■  ■  ■

我们找到最靠右 \(\ge k\) 的位置 \(p\),那么其左侧都变成了 \(k\),右侧则都能取,是后缀的和。

这样可以在 \(k\) 变化的时候,\(O(n)\) 动态维护不等式的右侧,称 \(S\)\(d\) 的前缀和:

  int p = n; // 找到最后一个高度 >= k 的位置
  for (int k = 1; k <= n; k++) {
    while (p > 0 && d[p - 1] < k) p--;

    ll sum = 1LL * k * (k - 1); // 完全图

    if (p > k) {
      sum += 1LL * (p - k) * k; // [k+1, p] 都 >= k
      sum += S[n] - S[p];       // [p+1, n] 都 < k
    }
    else sum += (S[n] - S[k]);  // [k+1, n] 都 < k
  }

这样在提前对 \(d\) 排序后,我们就在 \(O(n)\) 的时间里验证了所有的限制,判断了是否可图化。

A - 等价表述

注:这也是 Gallai 定理最好用的形式,非常强大。

我们找到 Ferrers 图的窦菲方 Durfee Square(左下角出发的最大的正方形),称它的边长是 \(s\),下图例子为 \(3\)

     5  4  3  3  1  1
1    □
2    □  □
4    ■  ■  ■  □
4    ■  ■  ■  □
6    ■  ■  ■  □  □  □

形式化地,\(s = \max\{ k \mid a_k \ge k \}\),即最后一个满足 \(a_k \ge k\) 的位置。同时还也有 \(s \le \sqrt S\)\(S = \sum d_i\)

我们发现限制的右侧有一个 \(k(k-1)\),它的值在 \(k \gt s\) 以后足够大,此后的都是更宽松的限制,不需要检查了。
也就是说,这个 Gallai 定理可以首先减小 \(k\) 的范围,即仅对 \(1 \le k \le s\) 考察:

\[\sum_{i=1}^k d_i \le k(k-1) + \sum_{i=k+1}^n \min(d_i, k) \]

接下来,由于总是有一个完整的正方形,右侧的求和号,可以改写为最下方 \(k\) 行之和,减去 \(k^2\) 的值。
这样一来,我们预处理 \(D\) 的共轭序列 \(C\),定理等价表述为对 \(1 \le k \le s\) 考察:

\[\begin{align} \sum_{i=1}^k d_i & \le k(k-1) + \left ( \sum_{i=1}^k c_i \right ) -k^2 \\ \sum_{i=1}^k d_i & \le \left ( \sum_{i=1}^k c_i \right ) - k \end{align} \]

喜大普奔,现在右侧的形式就非常容易计算了。

注意:这个形式仅能对 \(1 \le k \le s\) 考察,因为我们关于共轭序列的转化依赖这点,如果考察了 \(k \gt s\) 的部分,会导致错误判断。

注意:上式两侧都是凸函数:因为 \(d_i\) 是一个不升序列,故其前缀和是凸的。
同理,因为 \(c_i\) 是一个不升序列,加上一个凸函数 \(-k\),故其前缀和依然是凸的。
这个可能会在题目中非常有用。

B - 小优化(可能不重要)

Tripathi & Vijay (2003) 提出了和 Gale 定理一样的优化,只需要考虑 \(k=n\),以及满足 \(d_k > d_{k+1}\)\(k\),即可以跳过值相同的段,只考察靠右的断点。
这样的结果是,我们只需要考察 \(\sqrt S\)\(S = \sum d\) 个条件。

我们将原始形式的不等式两边移到一起去,构造:

\[D(k) = k(k-1) + \sum_{i=k+1}^n \min(d_i, k) - \sum_{i=1}^k d_i \ge 0 \]

不妨设 \(d_k = d_{k+1}\)(值相同),然后定义 \(D\) 的一阶差分 \(\Delta_k = D(k) - D(k-1)\),考察它的二阶差分:

\[\Delta_{k+1} - \Delta_k = 2 - 2[d_k \ge k] - C_k \]

这里 \(C_k\) 表示度数恰好等于 \(k\) 且下标 \(> k+1\) 的点数。

\(d_k \ge k\),二阶差分为 \(-C_k\),这个值必然 \(\le 0\),故在值相同的时候是局部上凸的。
\(d_k \lt k\),一阶差分为 \(2k - 2d_k > 2\) 始终递增,注意这个情况是在窦菲方右侧的。

C - 特殊情况(可能不重要)

Barrus et al. (2012):如果 除了最大值,最小值外,每个数字都不相同,则可无向图化等价于满足:

  1. (平凡的)总度数是偶数。
  2. (平凡的)\(d_i\) 的最大值不超过 \(n\),即 \(k = 1\) 时的限制。
  3. 只需要再检查一处 \(k = \max\{ i \mid d_i \ge i \}\) 的时候是否满足不等式。

第三个限制恰好在 Ferrers 图的窦菲方 Durfee Square 的边长 \(k=s\) 处。

证明

这个原文写了一车,我们发现了一个简洁一点的办法,考虑共轭形式:

\[\sum_{i=1}^k d_i \le \left ( \sum_{i=1}^k c_i \right ) - k \]

定义一阶差分 \(\Delta(k) = c_k - d_k -1\),二阶差分 \(\Delta^2(k) = (d_k - d_{k-1}) - (c_k - c_{k-1})\)

由于每个元素不同,有 \(d_k - d_{k-1} \ge 1\),而 \(c_k - c_{k-1}\) 表示恰好为 \(k\) 的元素数,不会超过 \(1\),故 \(\Delta^2(k) \ge 0\) 下凹。

所以这个我们这个函数总是先上凸(若干相同的最大值),再下凹。最小值只会在两个地方取到,我们说明为什么右边那个一定是 \(k=s\) 处:

image

我们在前面 “B -小优化” 里面已经说明了,在窦菲方 \(s\) 右侧,一阶差分为 \(2k - 2d_k > 2\) 斜率始终为正。现在只要说明在这个之前,斜率非正即可。

\(d_{s+1} \lt s\),则 \(c_s = s\),且始终有 \(d_s \ge s\),故 \(c_k - d_k - 1 \le -1\),斜率确实依然为负数。
\(d_{s+1} = s\),我们讨论它是不是最小值,若 \(s\) 是序列的最小值,那么 \(\forall k \in [1,s], c_k = n\),斜率 \(\Delta(k) = n - d_k - 1\) 始终为正。
这说明黑色部分没有出现斜率为负的部分,红色部分的谷底也不存在,不需要检查。
\(s\) 不是序列的最小值,则 \(c_s = s+1\),一阶差分为 \(s - d_s \le 0\) 也符合斜率非正。

于是我们就完成了证明,我擦这个东西配合杨表怎么有这种结论,我的直觉完全不靠谱。

\(1 \le k \le s\)\(a, c\) 地位明显是对称的,在一侧减掉 \(k\) 以后居然就这么神秘了。

证明

这个定理的证明比较困难,不能直接用 \(S-T\) 网络流说明,需要使用 Tutte 的 f-factor 定理。
这个 f-factor 定理的割条件给出了一个表达式,类似 Gale 定理的证明过程,可以让我们直接得到 Gallai 定理。
这里略。

例题

Good Bye 2018 - E

乱序给出 \(n\) 个点的度数 \(d_i\),你需要增加一个 \(d_{n+1}\),使得序列依然可无向图化,输出所有可能的解,可能无解。

$1 \le d_i \le n \le 5 \cdot 10^5 $

link

首先要总度数为偶数,可以提前判好 \(d_{n+1}\) 的奇偶性,接下来反复瞪着我们的定理(毕竟也没有别的手段了):

\[\sum_{i=1}^k d_i \le \left ( \sum_{i=1}^k c_i \right ) - k \]

考虑固定 \(k\),然后插入我们的 \(x = d_{n+1}\),要么放在左边,造成 \(x \le \dots\) 的限制;要么放在右边,造成 \(\dots \le x\) 的限制。

因此,合法的 \(x\) 范围必然是一个区间,我们直接二分答案以后,再次用 Gallai 定理检查即可,\(O(n \log n)\)

注意!共轭的等价表述只适用于 \(1 \le k \le s\)(因为转化依赖这个条件),不能往后继续考察,否则是错的。
这里 \(s = \max\{ k \mid a_k \ge k\}\)

2013 ICPC NEERC - K

班级里有未知数量的男孩和女孩,朋友关系是双向的。

已知每个女孩都恰好有 \(a\) 个女朋友、\(b\) 个男朋友。每个男孩都恰有 \(c\) 个女朋友,\(d\) 个男朋友。
请构造最少人数的班级,并输出一组连边方案。

\(1 \le a,b,c,d \le 50\)

link

让我们寻找一些必要条件,称女生有 \(G\) 个,男生有 \(B\)

  • \(B \ge b, B \ge d + 1\)
  • \(G \ge c, C \ge a + 1\)
  • \(aG \equiv dB \equiv 0 \pmod 2\) 内部度数是偶数。
  • \(G = \frac{kc}{\gcd(b,c)}, B = \frac{kb}{\gcd(b,c)}\) 连接两部的边提供相等度数。

其中前两个是 Gallai 定理化简来的,后两个是握手定理(也可以说是 Gallai 定理要求的)

我们枚举这个 \(k = 1, 2, \dots\) 然后检查上面的条件。构造答案的话有很多方法,贪心或者找一个正则图的构造方法。

某天梦到的题 2(不是题)

给定 \(n,m\) 表示有 \(n\) 个点,总度数恰好为 \(m\),请问有多少合法的度数序列,要求每个点度数大于零。

\(1 \le n,m \le 100\)

我们知道,最好用的形式是等价表述,对 \(1 \le k \le s\) 考察:

\[\sum_{i=1}^k d_i \le \left ( \sum_{i=1}^k c_i \right ) - k \]

但是由于 \(d\)\(c\) 会共用一个正方形,导致我们 dp 不方便填数字,这里介绍一个牛逼手段,引入 Frobenius 富比尼坐标:

     4  2  0  0  0  0
0    □
0    □  □
1    □  □  ■  □
2    □  ■  □  □
5    ■  □  □  □  □  □

\(a_i = d_i - i\) 表示第 \(i\) 列黑块上方的元素数量,也叫臂长 arm。
\(l_i = c_i - i\) 表示第 \(i\) 行黑块右侧的元素数量,也叫腿长 leg。
注:这里 arm 和 leg 的名字应该是在杨表里引入的。

因为都减去了 \(i\),所以 \(a\), \(l\) 两者都是 严格递减 的序列,且满足:

\[m = s + \sum a_i + \sum l_i \]

我们移项一下,把 \(d_i = a_i + 1\)\(c_i = l_i + 1\) 代入 Gallai 定理:

\[\begin{align} \sum_{i=1}^k (a_i + i) & \le \left ( \sum_{i=1}^k (l_i + i) \right ) - k \\ \sum_{i=1}^k a_i & \le \left ( \sum_{i=1}^k l_i \right ) - k \\ \end{align} \]

这样一来,我们就可以在 dp 的时候随便填 \(a\)\(l\) 的值了,满足总和为 \(m - s\),以及上面的限制。

设计 dp[x][cntA][cntL][dif][sum] 表示满足下面状态的方案数:

  • x 目前只能填入 \(x\) 的值 \(O(n)\)
  • cntA \(A\) 里填了几个 \(O(\sqrt m)\)
  • cntL \(L\) 里填了几个 \(O(\sqrt m)\)
  • dif \(L - A\) 的差值 \(O(m)\)
  • sum 总和 \(O(m)\)

我们从大到小枚举 \(x\),尝试放进 \(A,L,AL\),维护 difsum 即可。
当枚举到 cntL == cntA == k 时,检查一下 dif 是否合法 \(\ge k\)
最后输出答案的时候,需要枚举 \(s = 1,2 \dots \sqrt m\) 的值。

这样复杂度是 \(O(n m^3)\) 的,空间 \(O(m^3)\),有点困难,应该还能优化但是我不会,没有人类了。

参考资料

posted @ 2026-09-17 12:53  Aurora5090  阅读(11)  评论(0)    收藏  举报