Hall定理

Hall定理

对于一个两部分分别为 \(V_L\) , \(V_R\) 的二分图,且 \(|V_L|\leq |V_R|\) 。它存在一个大小为 \(|V_L|\) 的匹配(即左侧点完全被匹配,或称之为“完美匹配”),当且仅当 \(\forall S \subseteq V_L\) ,都有 \(|S| \leq |\cup_{x\in S} N(x)|\) (其中 \(N(x)\) 表示点 \(x\) 的邻居集)

证明

必要性

比较显然。如果对于左边一个点集它的 \(N(S)\) 都不足 \(|S|\) ,则必然不可能找到一个涵盖它的匹配。

充分性

考虑归纳法证明

  • 如果存在一个 \(S=N(S)\) ,则该子集本身存在完美匹配
    考虑删掉这个 \(S\)\(N(S)\),若出现不满足条件的集合 \(T\) ,那么我们考虑 \(S \cup T\),则有 \(|S\cup T| > |N(S\cup T)|\) 与我们的条件矛盾。

  • 如果所有 \(|N(S)|\) 都大于 \(|S|\),那么任取一个点 \(x\) 和它的匹配点 \(y\),删掉这两个点和它们所连的边。那么左右侧各删掉了一个点,剩下点必满足 \(|N(S)|>|S|\) .

以此类推,我们能做 1 操作的时候就做 1 操作,否则做 2 操作,即可得证。

推广

推论1. 对于一个 \(k\) 正则二分图,其必有完美匹配

如果存在一个左边的 \(|S|>|\cup_{x\in S} N(x)|\) ,则左边连出的点度为 \(k\times |S|\),而右边连到的集合大小却比 \(|S|\) 小,则右边必然有点度数 \(>k\) 的,矛盾。

推论2. 二分图 \((V_L,V_R)\) 的最大匹配为 \(|V_L|-\max_{S\subseteq V_L} (|S|-|\cup_{x\in S} N(x)|)=\min_{S\subseteq V_L}(|V_L|-|S|+|\cup_{x\in S} N(x)|)\)

第二个式子和第一个是等价的,所以我们只需要证明第一个。(稍微有点感性证明

  • 若只有一个 \(|S| > |\cup_{x\in S} N(x)|\),那么我们直接匹配最多可能匹配的,匹配不上的删掉。然后变就成了Hall定理的形式。

  • 对于剩下的情况,我们设 \(T=\set{S}\)(其中 \(|S| > |\cup_{x\in S} N(x)|\)),则我们只需证 \(max_{S\in T} (|S|-|\cup_{x\in S} N(x)|)\) 是不能匹配的点。我们任取其中两个 \(S_1,S_2\in T\)

    • \(S_1,S_2\) 不交,则 \(S_1\cup S_2 \in T\) 且我们不妨直接去考虑这个并集,也就是我们取了 \(max\) 点集和邻居集的差这个操作。

    • \(S_1,S_2\) 有交,那么它们不交的部分一定是各自考虑匹配,只用考虑它们的交集。若交集的邻居集大于等于交集的大小,那么只用考虑 \(S_1,S_2\) 不交的部分的匹配,这个集合也是属于 \(T\) 的;若交集的邻居集小于交集的大小,那么直接考虑 \(S_1 \cup S_2\)。其中这两种方式还是可以用 \(max_{S\in T} (|S|-|\cup_{x\in S} N(x)|)\) 刻画。

例题

[JOISC 2022] 蚂蚁与方糖

就是使用了推论2,这个结论在连边的范围是一段区间时非常好用,可以作为一些贪心策略的依据。

直接转化为实际意义,最大匹配就是“用总蚂蚁数- \(\max\) (选择的蚂蚁数-对应方糖数)”

\(\max\) 内的东西可以用线段树维护(别问怎么看出来的,可能就是区间修改+多次询问

考虑一种经典trick,对每个区间维护当前左/右端点选/不选蚂蚁时的最大的(选择的蚂蚁数-对应方糖数)的值。(准确来说只有钦定不选是必不选,钦定选择还包含这个地方暂时没有蚂蚁的情况)

每次修改时,加入蚂蚁就单点改;加入方糖,我们修改它能影响的区间 \([x-L,x+L]\)(即,在区间内选择蚂蚁时会计入这堆方糖的贡献)。

但注意到我们在线段树上合并两个区间时,这两个蚂蚁区间对应的方糖可能会有交集。

考虑如何维护这个东西。首先我们明确,如果两个蚂蚁的距离在 \(2L\) 以内,我们一定会选择这两个蚂蚁之间的所有蚂蚁。因为可选择的方糖数不变,而蚂蚁增多了。

那么 pushup 时如果在两侧区间各取一个已选择的蚂蚁,且这两个蚂蚁的最近距离在 \(2L\) 以内,合并两个区间的最大值,一定是钦定选择左区间的右端点和右区间的左端点;与此同时,这也就是会多算方糖的情况,我们只需要在此时把左右区间选择方糖的交集搞掉就行了。

那么我们线段树就只需要维护一个 t[x].f[0/1][0/1] 表示在这个区间内左右端点蚂蚁是否钦定选择的最大值,t[x].val表示在合并这个区间的左右儿子时会多算的方糖的贡献,最后我们还需要一个懒标记就行了。(注意懒标记打上的区间t[x].f[0/1][0/1],t[x].val都要更新

posted @ 2025-04-12 15:49  theWeeds'Defense  阅读(154)  评论(0)    收藏  举报