最悪の記者2
最悪の記者2
最近写的最认真的一篇题解了,毕竟是第一次知道霍尔定理,所以耗时也比较长。
霍尔定理:二分图 \(G(X\cup Y, E)\) 的左侧点集为 \(X\),右侧点集为 \(Y\),并钦定 \(|X| \le |Y|\)。记 \(N(S)\) 表示与 \(S\) 相邻的右侧点集。
二分图拥有完美匹配 \(\iff\) \(\forall S \subseteq X, |S| \le |N(S)|\)。
为了避免歧义,下文记原图中的左右侧点集分别为 \(A, B\),左右侧点分别为 \(a, b(a \in A, b \in B)\)。
分成左右两侧各 \(n\) 个点,分别从大到小排序,考虑将 \(A\) 向 \(B\) 连边(小 -> 大),容易发现右侧可连点是一段前缀,并且随 \(a\) 分数的减小,前缀的位置单调不降。按 \(a\) 分数从大到小的顺序给 \(a\) 安排一个可行的 \(b\),贪心地去做这个事情,可以得到不改变国籍时,最多能有多少个配对。
然后也曾误以为答案就等于 \(n\) 减去已配对数量,但这样做是错的,因为并不能保证剩下的点能构造出合法的连边。
以上是考试时的思路。
追究上述错误做法的问题根源,就是未匹配成功的点构成的二分图不具有完美匹配。于是我们需要对剩下的点考察二分图的完美匹配。
以下给出一个更加具体清晰的贪心过程:将所有分数随国籍一起按分数从小到大排序,如果分数相同,则 \(a\) 在前,\(b\) 在后。此时我们的任务仍然是将 \(A\) 和 \(B\) 连边,并且在保证尽可能多地将相同国籍的点连在一起时,保证其余的点能够构成完美匹配。为了区分直接匹配成功的点与其余的点,以下记 \(A^{'}, B^{'}(A^{'}\subseteq A, B^{'}\subseteq B)\) 表示未直接匹配成功的左右侧点集,类似地有 \(a^{'}, b^{'}(a^{'} \in A^{'}, b^{'} \in B^{'})\),并定义 \(a^{'}_i, b^{'}_i\) 表示 \(i\) 位置上的一个剩余的左/右侧点。
从左向右考虑,由于先进来的是 \(a\),所以这里要把 \(B^{'}\) 视作上文的 \(X\),否则扫完了也不能将任意一个国籍相同的可行点对进行配对(这里想一个小时才明白为什么)。由于最后 \(|A^{'}| = |B^{'}|\),因此这样考虑并不会导致结果发生变化。
为了判断 \(A^{'}, B^{'}\) 是否能构成完美匹配,可以维护 \(\min(|N(S)| - |S|)(S \subseteq B^{'})\) 的值。
对于一个确定的 \(S\),欲确定其对应的 \(|N(S)|\),则需考虑一个 \(b^{'}_i\) 对应的相邻的 \(a^{'}\) 的情况,发现与 \(b^{'}_i\) 相邻的 \(a^{'}\) 是 \(i\) 之前的所有 \(a^{'}\),即一段 \(A^{'}\) 的前缀,所以 \(|N(S)|\) 即为 \(S\) 中分数最大(即最靠右)的 \(b^{'}\) 的左侧的所有 \(a^{'}\) 的数量。
对于一个确定的 \(|S|\),由于要维护 \(\min(|N(S)| - |S|)\),因此我们只需要知道所有相同大小的 \(S\) 中对应的 \(|N(S)|\) 的最小值。根据上一段的分析,我们知道取 \(B^{'}\) 的一段前缀即可得到 \(|N(S)|\) 的最小值,因为这样可以使得 \(S\) 最右侧 \(b^{'}\) 的位置尽可能小,进而使得 \(A^{'}\) 前缀包含的元素尽量小。
我们可以来刻画 \(\min(|N(S)| - |S|)\) 了。即对于每种大小的 \(S\),求它们的 \(|N(S)| - |S|\) 的最小值。由于取得最小值的 \(S\) 是一段 \(B^{'}\) 的前缀,而 \(N(S)\) 是一段 \(A^{'}\) 的前缀,它们并起来成为了一个完整的剩余点集的前缀,稍微思考一下即可知我们需要维护的是 \(cntA^{'}_i - cntB^{'}_i\) 的前缀最小值,其中 \(cntA^{'}_i, cntB^{'}_i\) 分别表示到 \(i\) 位置时的 \(a^{'}, b^{'}\) 的数量。(理论上来说,只有当 \(i\) 位置上为 \(b^{'}\) 时这个式子才是有意义的,但 \(i\) 位置上为 \(a^{'}\) 或 \(a, b\) 时并不影响我们取得 \(|N(S)| - |S|\) 的最小值)
我们可以来进行配对了!
-
若当前点为 \(a_i\),则先把它视作一个未匹配点(\(a^{'}\)),在当前位置上打上一个 \(-1\) 标记。
-
若当前点为 \(b_i\),考虑与其国籍相同的 最近 的一个点 \(a^{'}_j(j < i)\) 进行配对,如果匹配 后 满足 \(\min(|N(S)| - |S|) \ge 0\),则进行匹配,消除 \(j\) 位置处的 \(-1\) ;否则加入未匹配点,在 \(i\) 位置处打上 \(+1\) 标记。
为什么选择最近的 \(a^{'}\):我们希望 \(\min(|N(S)| - |S|)\) 是尽可能大的。选择一个点 \(a^{'}_j\),将会对 \(k \in [j, 2n]\) 的所有 \(cntA^{'}_k\) 造成减一的影响 ,显然 \(j\) 应该是越大越好了。
以上过程容易用数据结构维护,需要实现区间加减、区间查询最小值。