从拟阵基础到 Shannon 开关游戏
从拟阵基础到 Shannon 开关游戏
本文中的定理名称翻译都有可能不准确!如果有找到错误的同学一定要联系我!
本文长期征集比较好的例题,如果有比较典型的题可以联系我
Part 0. 前言
拟阵非常强大,非常优美,但是在算法竞赛中却不常见。
你可能会说:这个容易,我 google 一下,博客一大堆。
但是事实上拟阵的教程非常少,而且大部分都有大篇幅的代数证明或者讲的及其不详细,代码实现也不完全适合算法竞赛使用。
本文致力于把拟阵的内容讲的尽量简洁易懂,但是尽量不把重要定理和命题的证明丢掉。如果你看不懂其中的证明部分,你可以跳过,对理解后文几乎没有影响。阅读本文不需要有线性代数知识,本文中只牵涉到可能和 OI 有关的内容。有兴趣深入探讨的读者可以阅读组合优化的书籍。
前置知识:
- Kruskal 算法
- 匈牙利算法
- 网络流
色觉障碍者可以没有障碍地阅读本文。(吐槽:原教程的图一个红色边一个绿色边让我咋看啊……取色器救我一命)
P.S. 我在学这玩意的时候很多东西都是用英文讲的,所以有一些词不太会翻,如果翻译有误请评论区。
Part 1. 拟阵的定义
1.1 拟阵 Matroid
【定义】拟阵是一个对向量空间中线性独立概念的概括与归纳的数学结构。
通俗的说,拟阵是描述独立关系的结构。
一个拟阵 \(\mathcal M = \langle X,\mathcal I\rangle\),其中 \(X\) 被称为 Ground Set,\(\mathcal I\) 被称为 Family of Sets,即 \(X\) 的独立子集的集合。如果一个集合 \(I \in \mathcal I\) (请注意 \(I\) 和 \(\mathcal I\) 之间的区别,一个是 I
,一个是 \mathcal I
,他们是不同的),则他是 \(X\) 的一个独立子集。
【性质】一个拟阵必须有下列性质:
- \(X\) 是一个有穷集合。
- (遗传性)一个独立子集的所有子集都是独立子集,即对于所有的 \(I \in \mathcal I, I' \subseteq I\),则有 \(I' \in \mathcal I\)。空集必须是独立集。
- (交换性质)若 \(A,B \in \mathcal I, |A| < |B|\),则 \(\exists x \in B \setminus A\) 使得 \(A + \{x\} \in \mathcal I\)。
如果我们需要证明一个形如 \(\langle X, \mathcal I\rangle\) 的东西是拟阵,我们只需要证明他满足以上 3 条性质即可。
这是一个拟阵:\(\mathcal M = \langle \{x, y, z\},\mathcal \{\varnothing, \{x\}, \{y\},\{z\},\{x, y\}, \{x, z\}\}\rangle\)。
1.2 基 Basis
【定义】所有极大独立集组成了拟阵的基,记号为 \(\mathcal B\)(即 \mathcal B
,与 \(B\) 即 B
有区别)。
【性质】
- 根据拟阵的第三条性质,拟阵中的极大独立集一定是最大独立集(否则可以加一个最大独立集中的元素,与“极大”矛盾),即极大独立集的大小都相等。
- 根据上一条,基中不存在一个元素为另一个元素的子集。
- 任何独立集都是基中一个元素的子集。因为我们可以不停地在这个集合里面添加元素直到他达到最大独立集的大小。
所以我们可以用拟阵的基来描述一个拟阵的 Family of sets。
1.3 圈 Circuit
【定义】如果一个不独立集合中除了本身以外的所有的子集都是独立集,则这个不独立集是一个圈。
【性质】
- 显然,圈中删去任意一个或多个元素都会导致集合拥有独立性。
- 根据上一条,不存在一个圈作为另一个圈的子集(否则不满足第一条)。
- 每一个不独立集的子集中一定含有一个圈。
- 两个圈的并中删除任意一个元素形成的集合的子集中仍然含有一个圈。(对于一些种类的拟阵对于圈 \(A\) 和圈 \(B\) 我们有 \((A \setminus B) \cup (B \setminus A)\) 包含一个圈)
所以我们可以用拟阵的所有圈来描述一个拟阵的 Family of sets。
1.4 秩 rank
【定义】拟阵的秩是 ground set 的最大独立子集的大小。
【定义】秩函数 \(r(S)\) 表示 \(S\) 的最大独立子集的大小。其中 \(S\) 必须是 ground set 的一个子集。\(r(S)\) 被称为 \(S\) 的秩。
【性质】
- \(r(S) \le |S|\)。
- \(r(\varnothing)=0\)。
- 独立集的秩为独立集的大小。
- ground set 的秩等于拟阵的秩。
- (单调性)\(S\) 的子集的秩不大于 \(S\) 的秩。
- 若我们在 \(S\) 中加入一个元素,则 \(S\) 的秩要么不变,要么增加 \(1\)。
- (次模性)\(r(A)+r(B) \geq r(A \cup B) + r(A \cap B)\)。
- (次模性推论)\(r((A \setminus B) \cup (A \cap B)) + r((B \setminus A) \cup (A \cap B)) \geq r(A \cup B) + r(A \cap B)\)。
只需要证明第一条,第五条和第七条性质就可以证明某个秩函数是合法的。
1.5 强基交换定理 Strong Basis Exchange Lemma
这部分柿子比较多,你可以只看结论不看证明。
【定义】定义 \(\operatorname{span}(A) = \{x \in X |\ r(A \cup \{x\}) = r(A)\}\)。
【性质】
如果 \(A \subseteq B\),则 \(\operatorname{span}(A) \subseteq \operatorname{span}(B)\)。
Proof. 假设 \(e \in \operatorname{span}(A)\),由性质 7,\(r(A \cup \{e\})+r(B) \geq r((A \cup \{e\})\cap B) + r(B \cup \{e\} \geq r(A) + r(B \cup \{e\}))\)。
因为 \(e \in \operatorname{span}(A)\),我们有 \(r(A) = r(A \cup \{e\}) \implies r(B) \geq r(B \cup \{e\})\)
\(\implies r(B) = r(B \cup \{e\}) \implies e \in \operatorname{span}(B)\)。
所以 \(\operatorname{span}(A) \subseteq \operatorname{span}(B)\)。\(\square\)
\(\forall x \in \operatorname{span}(A)\),\(\operatorname{span}(A) = \operatorname{span}(A \cup \{x\})\)。
Proof. 由性质 9,我们知道 \(\operatorname{span}(A) \subseteq \operatorname{span}(A \cup \{e\})\),所以我们只需要证明 \(\operatorname{span}(A \cup \{e\}) \subseteq \operatorname{span}(A)\)。
令 \(e \in \operatorname{span}(A), f \in \operatorname{span}(A \cup \{e\})\)。由性质 7,\(r(A \cup \{e\}) + r(A \cup \{f\}) \geq r(A \cup \{e, f\}) + r((A \cup \{e\}) \cap (A \cup \{f\})) \geq r(A \cup \{e, f\}) +r(A)\)。
因为 \(r(A) = r(A \cup \{e\})\),我们有 \(r(A \cup \{f\}) \geq r(A \cup \{e, f\}) \implies r(A \cup \{f\})=r(A \cup \{e, f\})\)。
所以 \(r(A \cup \{f\}) = r(A) \implies f \in \operatorname{span}(A)\)。\(\square\)
由性质 10,我们有 \(\operatorname{span}(\operatorname{span}(A)) = \operatorname{span}(A)\)。
【引理】令 \(B\) 和 \(B'\) 为 \(\mathcal B\) 的两个元素。则 \(\forall x \in B \setminus B'\),\(\exists\ y \in B' \setminus B\) 使得 \(B \setminus \{x\} \cup \{y\} \in \mathcal B\) 并且 \(B' \setminus \{y\} \cup \{x\} \in \mathcal B\)。
Proof. 假设 \(x \in B \setminus B'\)。因为 \(B' \in \mathcal B\),\(B' \cup \{x\}\) 包含一个圈 \(C\),并且 \(C\) 必须包含 \(x\)。
所以 \(x \in \operatorname{span}(C - x) \implies x \in \operatorname{span}((B \cup C) \setminus \{x\})\)。
根据以上性质,\(\operatorname{span}((B \cup C) \setminus \{x\}) = \operatorname{span}(B \cup C) = X\)。
所以 \((B \cup C) \setminus \{x\}\) 包含了一个基中的元素 \(B''\)。则 \(B \setminus \{x\}\) 和 \(B''\) 都具有独立性,并且 \(|B''| > |B - x|\)。
所以 \(\exists \ y \in B'' \setminus(B \setminus \{x\})\) 满足 \((B \setminus \{x\}) \cup \{y\} \in \mathcal B\)。
而 \(B'' \setminus (B \setminus \{x\}) \subseteq ((B \cup C) \setminus \{x\}) \setminus (B \setminus \{x\}) \subseteq C \setminus \{x\}\),所以 \(\exists \ y \in C \setminus \{x\}\) 是的 \(B \setminus \{x\} \cup \{y\} \in \mathcal B\)。
因为 \(C\) 是一个圈并且 \(x, y \in C\),我们有 \(B' \setminus \{y\} \cup \{x\} \in \mathcal B\)。\(\square\)
1.6 独立性谕示 Independence Oracle
你可以把他理解为一个可以回答一个子集是否独立的结构。拟阵交算法的复杂度和 Independence Oracle 询问的复杂度相关。
Part 2. 常见拟阵
下面列举了一些常见的拟阵,但是远不止这些。我们有时候需要根据题目要求构造拟阵。
2.1 均匀拟阵 Uniform Matroid
\(S\) 独立当且仅当 \(|S| \le k\) 的拟阵被称为均匀拟阵。容易证明这是一个拟阵。
所有大小为 \(k\) 的子集都属于基,所有大小为 \(k+1\) 的子集都是圈。
Trivial Matroid 对应 \(k=0\) 的情况,Complete Matroid 对应 \(k=|X|\)。
2.2 线性拟阵 Linear (algebra) Matroid
\(X\) 包含了一些向量。如果 \(S\) 独立当且仅当 \(S\) 线性独立。(即:不存在一个向量能够表示为其他向量的线性组合)其符合拟阵的三条性质,读者自证不难。(蛤?你不会证?2.4 和 2.5 写了两个证明示例)
向量的线性基就是线性拟阵的基。线性拟阵的圈满足任意向量可以表示为其他向量的线性组合。
回答线性拟阵的 Oracle 询问可以用高斯消元。
2.3 有色拟阵 Colourful Matroid
有色拟阵的 ground set 里面的元素都上色了,每一个元素都上了一种颜色。
如果子集中的元素的颜色各不相同,则子集有独立性。不难发现,在有色拟阵中,秩函数即为颜色数。
2.4 图拟阵 Graphic Matroid
图拟阵的 ground set 是无向图的所有边,而一个子集 \(S\) 独立当且仅当 \(S\) 中的边不形成环。
基是所有的生成树,圈是图中的所有简单环。可以用并查集回答 Oracle 询问。
图拟阵的 ground set 显然为有穷集,并且遗传性也是显然的;我们只需证明交换性质。
注意到图中的一个含有 \(k\) 条边的森林含有 \(n-k\) 个联通块,所以若 \(|B| > |A|\),\(A\) 森林的树的数量一定比 \(B\) 多。不难发现,\(B\) 一定有一颗树 \(T\) 的节点在 \(A\) 中对应了两棵树。因为 \(T\) 是联通的,所以必定存在一条边是连接 \(A\) 中两棵树的节点的。故将这条边加到 \(A\) 中不会破坏独立性。\(\square\)
2.5 划分拟阵 Partition Matroid
\(X_1, X_2, \ldots, X_m\) 是 \(X\) 的一个划分,相应有 \(m\) 个非负整数 \(d_1, d_2, \ldots, d_m\)。\(X\) 的子集 \(S\) 具有独立性当且仅当 \(\forall i \in [1, m]\) 有 \(|S \cap X_i| \leq d_i\)。
划分拟阵的 ground set 显然为有穷集,并且遗传性也是显然的;我们只需证明交换性质。
令 \(A, B \in \mathcal I\),\(|B| > |A|\)。我们有 \(|A| = \sum |A \cap X_i|<\sum |B \cap X_i| = |B|\),所以至少存在一个 \(i\) 使得 \(|A \cap X_i| < |B \cap X_i| \leq d_i\),故我们将 \((B \cap X_i) \setminus A\) 中的任意一个元素加入到 \(A\) 中至多使 \(|A \cap X_i| \le d_i\),能够保持独立性。\(\square\)
2.6 截断拟阵 Truncated Matroid
我们可以在不破坏拟阵性质的前提下对拟阵的秩进行一定的限制。
比如限制有色拟阵:限制其基为至多 \(k\) 种颜色。限制图拟阵:基选出的边使得图中至少有 \(n-k\) 个联通块。
当所有大小大于等于 \(k\) 的独立集都被移除,拟阵的性质显然不会被破坏。
2.7 部分拟阵 Matroid on a subset of ground set
我们可以直接把 ground set 变成原本的一个子集,并且对 family of sets 做出一些相应的修改,这样不会破坏拟阵的性质。这是因为独立性和原本 ground set 中含有哪些元素无关。
我们也可以说对于 \(X' \subseteq X\),\(r(X')\) 同时也是拟阵 \(\mathcal M' = \langle X', \mathcal I' \rangle\) 的秩。
2.8 拟阵的和 Expanded Matroid & Direct Matroid Sum
如果两个拟阵的 ground set 里面的元素不影响彼此的独立性,那么我们可以简单的把两个拟阵合并起来。
即:\(\mathcal M_1 = \langle X_1, \mathcal I_1 \rangle\),\(\mathcal M_2 = \langle X_2, \mathcal I_2 \rangle\),\(\mathcal M_1 + \mathcal M_2 = \langle X_1 \cup X_2, \mathcal I_1 \times \mathcal I_2 \rangle\)。这里的 \(\times\) 是笛卡尔积。
Part 3. Rado-Edmonds 算法
Rado-Edmonds 算法可以找到拟阵的基。
3.1 不带权的情况
根据拟阵的第三条性质,我们可以往一个初始为空的集合中不断加入元素,每次扫描 ground set。则我们有一个 \(\mathcal O(rn)\) 次 Oracle 询问的算法,其中 \(r\) 为拟阵的秩,\(n = |X|\)。
但是我们注意到如果在某一个时刻某一个元素不能加入当前集合,则在未来的任意一个时刻也不会加入。所以每次不必扫描整个 ground set,只要在整个过程中扫描一遍就好了,所以我们就有了一个 \(\mathcal O(n)\) 次 Oracle 询问的算法。
3.2 带权的一般情况 & 重温 Kruskal 算法
但是如果 ground set 中的元素带权,我们就要找到一个权值之和最小的最大独立子集。
如果是图拟阵就变成了最小生成树问题,那么我们可以考虑使用类似的贪心算法解决该问题。
回忆一下 Kruskal 算法的过程:我们尝试从大小为 \(k\) 的最小权值最大独立集(记为 \(A\))转移到大小为 \(k+1\) 的(记为 \(B\))。
根据拟阵的第三条性质,我们可以至少往 \(A\) 中加入一个 \(B\) 中的元素。记这个元素为 \(y\),则我们有 \(A \leq B \setminus \{y\}\) 以及 \(B \le A \cup \{y\}\)。
如果我们往两边的柿子中同时加入 \(y\) 可得 \(A \cup \{y\} \le (B \setminus \{y\}) \cup \{y\}\) 以及 \(A \cup \{y\} \le B\)。
所以 \(B \le A \cup \{y\} \le B \implies B = A \cup \{y\}\)。
所以我们每次在不破坏独立性的前提下加入权值最小的元素就能求出最小权值最大独立集。
所以你又重温了 Kruskal 算法并且知道了如何用这个向普及组小朋友装逼我们就有了一个 \(\mathcal O(n \log n)\) 排序以及 \(\mathcal O(n)\) 次 Oracle 询问的算法了。
3.3 拟阵和贪心的关系
由此我们看出,拟阵是证明贪心策略的重要方法。(但是不是所有贪心策略都一定能用拟阵证明)
这一部分内容在一篇洛谷日报 拟阵与最优化问题 中也有提到,但是不完全一样。
Part 4. 拟阵交
4.1 功能
有两个拟阵 \(\mathcal M_1 = \langle X, \mathcal I_1\rangle\) 和 \(\mathcal M_2 = \langle X, \mathcal I_2 \rangle\)。我们要求出最大的 \(\mathcal I_1 \cap \mathcal I_2\) 的集合,即在 \(\mathcal M_1\) 和 \(\mathcal M_2\) 中都有独立性的最大集合。
4.2 例子
4.2.1 上色图生成树问题
有一张无向图,每条边有一个颜色。你需要找到一个生成树使得生成树中每一种颜色的边不超过一条。
显然,这是有色拟阵和图拟阵的交。
4.2.2 染色线性向量问题
给定一些向量,每个向量都染色了,你需要找到最大的集合使得没有相同颜色的向量,且集合中的向量线性无关。
显然,这是有色拟阵和线性拟阵的交。
4.2.3 二分图匹配
这是一个经典的问题。
警告:不要用拟阵交来做二分图匹配,因为时间复杂度为 \(\mathcal O(|E|^3)\),大部分 OJ 上面的模板题都无法通过!
二分图匹配其实就是“没有两条选出边共用一个顶点”,我们将其简化成为“没有两条选出的边共用一个在右边的顶点”。
右边的拟阵可以用一个划分拟阵来表示,左边的拟阵也是相似的情况。即:
\mathcal M_2= \langle E, \mathcal I_2= \{F:|F \cap \operatorname{adj}_v| \le 1, v \text{ is in the left part}\}\rangle
\]
算出两个拟阵的交就可以了。
4.2.3 哈密尔顿回路问题
多个拟阵的交的例子:哈密尔顿回路问题。
在有向图上面,构造以下三个拟阵:
- 确保每个点出度至多 \(1\)(具体的,用一个有色拟阵,每个顶点连出的边都是同一个颜色)
- 确保每个点入度至多 \(1\)(具体的,用一个有色拟阵,连入每个顶点的边都是同一个颜色)
- 确保无环(具体的,忽略边的方向,构造图拟阵)
求出这三个拟阵的交就能解决问题啦!
所以……你觉得多个拟阵的交有多项式时间复杂度的算法吗?没有!
4.2.4 其他题目
算法竞赛中还有一些其他的拟阵交的题,我放在 Part 7 例题里面啦~
4.3 算法
4.3.1 交换图 Exchange Graph
首先我们考虑如何求出一个公共的极大独立子集。
根据 1.5 Strong Basis Exchange Lemma,我们可以交换基的元素。同时,根据截断拟阵的定义,我们可以把同一个大小的独立集看作是一个新拟阵的基。所以,我们可以交换等大独立集中的元素。
那么我们如何描述这些交换关系呢?
考虑使用一张交换图来表示这种关系。对于独立集 \(S\),交换图 \(\mathcal D(S)\) 是一个二分图,如果我们能把 \(x\) 换成 \(y\) 而可以保持独立性,则我们连 \((x,y)\) 这条边。形式化的,如果 \(x \in S, y \in X \setminus S, S \setminus \{x\} \cup \{y\} \in \mathcal I\),则 \((x, y) \in E\)。也就是说,在交换图上的一条边的意义是交换某一个元素。
如图 1 所示的无向图,\(S = \{1, 2, 5\}\) 对应的交换图如图 2。
那么交换图有什么用呢?
Lemma 4.3.2
如果这个引理的证明看不懂可以尝试从交换图的意义出发感性理解。
【引理】两个独立集 \(S,T\) 满足 \(|S|=|T|\),则在 \(\mathcal D(S)\) 中一定存在 \(S \setminus T\) 和 \(T \setminus S\) 间的完美匹配。
Proof. 定义截断拟阵 \(\mathcal M' = \langle X, \{I' \in \mathcal I | |I'| \le |S|\}\rangle\),使 \(S, T \in \mathcal B'\)。
令 \(x \in T \setminus S\),则根据 Strong Basis Exchange Lemma 我们有 \(\exists\ y \in S \setminus T\) 使得 \(S \setminus \{y\} \cup \{x\} \in \mathcal B'\) 并且 \(T \setminus \{x\} \cup \{y\}\in \mathcal B'\)。
基中的元素一定都是独立集,所以我们可以得出 \((y,x)\) 一定是 \(\mathcal D(S)\) 中的一条边。
然后我们可以将 \(T\) 替换为 \(T \setminus \{x\} \cup \{y\}\)。不难发现 \(S \setminus T\) 比 \(S \setminus (T \setminus \{x\} \cup \{y\})\) 多一个元素。
不难归纳得我们一定可以得到一个完美匹配。\(\square\)
Lemma 4.3.3
上面的引理的逆命题显然是不成立的。我们可以随意选择两条边 \((a,b)\) 和 \((c,d)\),这是不能保证成立的。如果 \(b\) 和 \(d\) 在一起不独立那就显然不行了。
如图中,原来的 \(S = \{(1,2), (2,3), (3,5), (5,6)\}\)。如果我们把 \((1,2)\) 换成 \((2,4)\),把 \((5,6)\) 换成 \((4,5)\),这两个操作单独做都没有问题,但是如果同时做就破坏独立性了。
那么我们如何判断这个匹配是否会破坏独立性呢?
事实上,我们注意到一个圈有多种方法可以通过若干次交换变成一个独立集。比如上述例子中可以把 \((5,6)\) 换成 \((2,3)\),把 \((1,2)\) 换到 \((3,5)\),也能得到同样的圈。
那么是不是只有一个匹配就不会破坏独立性呢?请看证明。
【引理】独立集 \(S\) 和集合 \(T\) 满足 \(|S|=|T|\),若在 \(\mathcal D(S)\) 中存在 \(S \setminus T\) 和 \(T \setminus S\) 间的唯一匹配,则 \(T\) 具有独立性。
Proof. 令唯一匹配为 \(N\)。给 \(\mathcal D(S)\) 中的边标向,\(N\) 中的边从 \(X \setminus S\) 到 \(S\),不在 \(N\) 中的边从 \(S\) 到 \(X \setminus S\)。由于匹配唯一,所以现在 \(\mathcal D(S)\) 是一个 DAG。
我们对其拓扑排序,并且使得所有的边从编号小的节点指向编号大的节点。
则 \(N = \{(y_1, x_1), (y_2, x_2), \ldots, (y_t, x_t)\}\),对于 \(i<j\),\((y_i, x_j)\) 肯定不在 \(N\) 中。
假设 \(T\) 不独立,则 \(T\) 包含了一个圈 \(C\)。显然,\(C\) 中至少包含一个 \(T \setminus S\) 的元素,因为 \(C \subseteq T\) 并且 \(S \in \mathcal I\)。
因为对于 \(x \in C \setminus \{x_i \}\),\((y_i, x)\) 不在 DAG 中,所以 \(x \in \operatorname{span}(S \setminus \{y_i\})\)。所以 \(C \setminus \{x_i\} \subseteq \operatorname{span}(S \setminus \{y_i\})\)。
所以 \(\operatorname{span}(C \setminus \{x_i\}) \subseteq \operatorname{span}(\operatorname{span}(S \setminus \{y_i\})) = \operatorname{span}(S \setminus \{y_i\})\)。
由于 \(C\) 是一个圈,\(x_i \in \operatorname{span}(C \setminus \{x_i\}) \implies x_i \in \operatorname{span}(S \setminus \{y_i\})\)。
因为 \((x_i, y_i) \in \mathcal D(S)\),所以矛盾。所以 \(T\) 一定独立。\(\square\)
蛤?你不太理解?通俗的讲一讲。
我们尝试构造一个圈使得某个独立集到他只有一种匹配。
首先,显然的是圈里面至少要有两个空位才能匹配到即 \(|C \setminus S| \geq 2\)。(如果交换了连接 \(C\) 的两个元素的一条边,那么就没法到 \(C\) 了,删掉的边不能添回来)如果只有一个空位,那么交换图中一定不存在换到这个空位的边,因为如果换过来那么单次操作就会破坏独立性,和交换图的定义矛盾。
我们想要把两边这两条边对应换到中间的圈中,但是我们要限制他使得左边的边不能换到右边的空当中,右边的边不能换到左边的空当中。注意到只有交换图里面存在的东西才能交换,所以我们只能在两边构造两个圈。如图
但是我们突然发现,为什么实线描出来的东西(即原来的独立集)不是独立集,是一个圈!!1
咍咍,这是因为在线性组合的意义下某一个元素 \(x\) 和某个包含 \(x\) 的圈去除 \(x\) 之后是一样的。(这是圈的名字的由来)
矛盾了,所以不存在这种构造。原命题成立。
读到这里,你可能要说:这个和拟阵交有什么关系?
4.3.4 交换图与增广路 Augumenting Paths
接下来把前面的内容和拟阵的交联系上。
对于 \(I \in \mathcal I_1 \cap \mathcal I_2\),我们定义交换图 \(\mathcal D_{\mathcal M_1, \mathcal M_2}(I)\) 是一个有向二分图,左右边分别为 \(I\) 和 \(X \setminus I\)。边 \((y,x)\) 在图中当且仅当 \(I \setminus \{y\} \cup \{x\} \in \mathcal I_1\);边 \((x,y)\) 在图中当且仅当 \(I \setminus \{y\} \cup \{x\} \in \mathcal I_2\)。相当于合并了两个在单一拟阵上的交换图。
我们举一个例子来说明。考虑例 1 的一个简单的例子。图长这样,只有中间一条边是红色,其余为黑色。
当 \(I = \{(1,2),(2,3),(3,4)\}\),\(\mathcal D_{\mathcal M_1}(S)\) 和 \(\mathcal D_{\mathcal M_2}(S)\) 分别如左和右图所示。
\(\mathcal D_{\mathcal M_1, \mathcal M_2}\) 如下图所示。(边的方向可能不是很清楚,黑色的都是左到右,红色的都是右到左)
这张图中只有两个独立集:\(I = \{(1,2),(2,3),(3,4)\}\) 和 \(J = \{(1,3), (2,3), (2,4)\}\)。可以看到,\(I \setminus J = \{(1,2), (3,4)\}\) 和 \(J \setminus I = \{(1,3), (2,4)\}\) 之间存在一个完美匹配。
那为什么要给这张图标上方向呢?别急,我们重新画一下图。
我们可以发现,这样标向可以使得环中总是左边和右边的点交错的模式。所有环一定都是偶环。
我们定义 \(X_1 = \{x \notin I | I \cup \{x\} \in \mathcal I_1\}\),\(X_2 = \{x \notin I | I \cup \{x\} \in \mathcal I_2\}\)。
显然,\(X_1\) 中的任意一个元素可以通过某条路径到达 \(X_2\) 中的任意一个元素。
首先我们可以考虑几个特殊情况。
- 如果 \(X_1 \cap X_2\) 非空,则我们显然可以直接把这个元素加到 \(I\) 中去,然后进行剩下操作。
- 如果 \(X_1\) 或者 \(X_2\) 为空集,则此时 \(I\) 已经是一个基了(如果 \(I\) 不是基,我们一定可以找到至少一个元素插入 \(I\)),也就是说我们求出了拟阵交。
那么我们如何满足只存在一个完美匹配呢?如果我们找到一条可以“抄近道”的路,那么这条路一定不行。
我们称不能“抄近道”的路为增广路。不能抄近道即不存在从路径某一点之前的某一点直接连到之后那个点的边。
但是由于 \(X_1\) 和 \(X_2\) 都在右半边,所以如果直接对原图求增广路,增广路的长度将会是奇数。所以右边将会有一个节点匹配不到。
我们为了解决这个问题,在交换图中增加一个不影响最终答案的临时节点(即:与其他所有点都独立的节点)。记这个节点为 \(t\)。我们把 \(t\) 连接到 \(X_1\) 和 \(X_2\) 中的元素上去。然后这个问题就解决了。
所以我们直接进行选出的增广路中的边所对应的交换操作,在这一步中我们可以忽略临时节点 \(t\)。所以我们每找到一条增广路我们就能够把 \(I\) 的大小增加 \(1\)。形式化的,\(P\) 是增广路上面除了 \(t\) 的节点集合,则每次操作我们都将 \(I\) 替换为 \((I \setminus P) \cup (P \setminus I)\)。
4.3.5 Edmonds-Lawler theorem (Min-max Formula)
但是这样一定可以找到拟阵交吗?我们发现,如果增广路不存在,\(X_1\) 或 \(X_2\) 为空不一定满足。
对于集合 \(U\),我们把 \(X\) 分成两个部分 \(U\) 和 \(X \setminus U\),则显然 \(S\) 在某一个部分中的部分一定对两个拟阵都具有独立性。
我们可以用秩函数列四个不等式:
|I \cap U| \le r_1(U) \\
|I \cap U| \le r_2(U) \\
|I \cap (X \setminus U)| \le r_1(X \setminus U) \\
|I \cap (X \setminus U)| \le r_2(X \setminus U)
\end{cases}
\]
由 \((1) + (4)\) 得 \(|I \cap U| + |I \cap (X \setminus U)| \le r_1(U) + r_2(X \setminus U) \implies |I| \le r_1(U) + r_2(X \setminus U)\)。
所以我们可以得出
\]
【定理】当找不到增广路的时候,我们记集合 \(U\) 表示 \(\mathcal D_{\mathcal M_1, \mathcal M_2}(I)\) 中可以到达 \(X_2\) 中某个点的点之集合,则
\]
Proof. 显然 \(X_2 \subseteq U\),并且 \(X_1 \cap U = \varnothing\)。否则我们就可以找到一条增广路。我们需要证明 \(r_1(U) = |I \cap U|\) 和 \(r_2(X \setminus U) = |I \cap (X \setminus U)|\)。
假设 \(r_1(U) \neq |I \cap U|\)。因为 \(I \cap U\) 独立,并且 \(I \cap U \subseteq U\),所以 \(|I \cap U| < r_1(U)\)。
则需要存在 \(x \in U \setminus I\) 满足 \(U \cap I \cup \{x\} \in \mathcal I_1\)。
因为已经找不到增广路了,所以 \(I \cup \{x\}\) 要么不独立,要么恰好含有一个环。这个环至少包含一个不在 \(U \cap I \cup \{x\}\) 中的元素。
无论是那种情况都存在 \(y \in I \setminus U\) 使得 \(I \setminus \{y\} \cup \{x\} \in \mathcal I_1\)。
但是如果这样 \((y,x)\) 这条边存在于 \(\mathcal D_{\mathcal M_1, \mathcal M_2}(I)\) 中,所以 \(x \in U \implies y \in U\)。矛盾。
所以 \(r_1(U) = |I \cap U|\)。
同理可得 \(r_2(X \setminus U) = |I \cap (X \setminus U)|\)。
所以 \(\max |I| = r_1(U) + r_2(X \setminus U)\)。\(\square\)
所以算法的正确性证明完了。再总结一下算法流程:
重复执行下列步骤:
- 建交换图
- 算出 \(X_1\) 和 \(X_2\)
- 找增广路,找不到就退出
- 更新当前 \(I\)
4.4 复杂度
记 \(r = \max(r_1(X), r_2(X))\)。
我们可以用 \(\mathcal O(rn)\) 次 Oracle 询问建出交换图,\(\mathcal O(n)\) 次询问找到 \(X_1\) 和 \(X_2\),并且找到增广路的时间复杂度为 \(\mathcal O(rn)\)。
因为我们需要增广至多 \(r\) 次,所以算法的时间复杂度为 \(\mathcal O(r^2n)\) 次 Oracle 询问。大多数情况下使用这个算法就足够了。
4.5 优化
4.5.1 一般情况的优化
我们可以看到复杂度的瓶颈其实是建交换图这一步,所以我们干脆跳过这一步,在找增广路的时候同时进行建图。
每次找最短的增广路(并且使用更快的寻找增广路的算法(?)),就可以做到 \(\mathcal O(r^{1.5}n)\) 次 Oracle 询问了。
前两句话可能讲的比较模糊,同学们可以看这篇论文:William H. Cunningham. Improved Bounds for Matroid Partition and Intersection Algorithms.[J]. SIAM J. Comput.,1986,15(4)
(顺便说一句,如果有同学能看这篇论文私信我)
4.5.2 针对有色拟阵的 Oracle 询问优化
这个应该比较容易吧……
直接维护一个存储每个颜色的数量的数组即可(通过增删操作实现)。每次增删和 Oracle 询问都容易做到 \(\mathcal O(1)\)。
4.5.3 针对图拟阵的 Oracle 询问优化
针对图拟阵,我们有两种回答 Oracle 询问的方式:
- 我们可以执行 \(r\) 次去掉一条边,数联通快这一操作。如果边连接了两个不同的联通快,则我们可以使用这条边。所以我们每次建立交换图是 \(\mathcal O(n)\)。但是空间复杂度是 \(\mathcal O(rn)\),如果出题人故意卡,就……
- 考虑我们可以换某条边的条件是这条边连接了两棵树(否则就会有环)。然后可以转化成 LCA 问题求解。(不推荐使用)
4.5.4 针对线性拟阵的 Oracle 询问优化
比较朴素的想法是用高斯消元法,时间复杂度 \(\mathcal O(r^2m)\)。如果向量空间是 \(\mathbb Z _2^m\),那么我们可以用 bitset 优化到 \(\mathcal O(\frac {r^2m} w)\)。
考虑优化,如果我有向量集合的基,我们就可以做到做到 \(\mathcal O(rm)\),因为我们只需要消去一个向量。
因为高斯消元之后我们不容易移除一个原有向量,所以我们对于每个可能被删去的向量预处理该向量删去之后的基。
预处理 \(\mathcal O(r^3m)\),每条边 \(\mathcal O(rm)\)。
4.6 带权拟阵交 Weighted Matroid Intersection
每个元素都带有一个权值 \(w_x\) 的情况下,如何求出权值之和最大的交呢?我们定义极限独立集为大小最大的独立集中权值最大的独立集。很显然,我们要求的就是极限独立集。
其实做法和前面是一样的,但是我们要对交换图做一些改动:如果 \(x \in I\) 则 \(x\) 的权值为 \(w_x\),否则为 \(-w_x\)。
我们每次找到最短的增广路,第一关键字为长度(交换图上的权值之和),第二关键字为路径的边数。
因为有负权,所以我们必须使用 Bellman-Ford 算法解决。
PS. 如果使用队列优化的 Bellman-Ford 算法将会改善算法的常数,并且在大多数图中都取得不错的运行效率。
Min-Max 方程有一个带权的版本:
\]
Part 5. 拟阵并
如果下文中的证明你看不懂,那么只看结论也是没有关系的。
5.1 对偶拟阵 Dual Matroid
5.1.1 对偶拟阵
【定义】对于任何拟阵 \(\mathcal M = \langle X, \mathcal I \rangle\),我们定义其对偶拟阵为 \(\mathcal M^* = \langle X, \mathcal I^*\rangle\),其中 \(\mathcal I^* = \{S \subseteq X | \exists B \in \mathcal B, B \subseteq X \setminus S\}\)。
感兴趣的读者可以自己证明 \(\mathcal M^*\) 是一个拟阵。
Lemma 5.1.2
【引理】\(\mathcal M^*\) 的秩函数是 \(r_{\mathcal M^*}(S) = |S| + r_\mathcal M (X \setminus S) - r_\mathcal M(X)\)。
Proof. 显然,\(r_{\mathcal M^*}(S) = \max _{I \subseteq S, I \in \mathcal I^*} |I| = |S| - \min _{B \in \mathcal B_{\mathcal M}}|S \cap B|= |S| + r_\mathcal M(X \setminus S) - r_\mathcal M(X)\)。
秩函数的第一条性质是显然满足的。
假设 \(T \subseteq S \subseteq X\)。则 根据 \(r_\mathcal M(\cdot)\)(下面简写为 \(r(\cdot)\))的次模性
\leq |T| - r(X)+r(X \setminus S)+(|S|-|T|) = |S| - r(X)+r(X \setminus S) = r_{\mathcal M^*}(S)
\]
所以 \(r_{\mathcal M^*}\) 具有单调性。
令 \(I,J \subseteq X\),\(T = X \setminus I\),\(S = X \setminus J\)。
根据 \(r(\cdot)\) 的次模性,我们有 \(r(T \cup S) + r(T \cap S) = r(X \setminus (I \cap J))+r(X \setminus(I \cup J)) \leq r(X \setminus I) + r(X \setminus J)\)。所以 \(|I \cap J| + |I \cup J| = (|I| + |J| - |I \cap J|) + |I \cap J| = |I| + |J|\)。所以 \(r_{\mathcal M^*}(I \cup J) + r_{\mathcal M^*}(I \cap J) \leq r_{\mathcal M^*}(I) + r_{\mathcal M^*}(J)\)。
所以 \(r_{\mathcal M^*}\) 具有次模性。\(\square\)
5.1.2 图拟阵对偶的性质
其实对偶拟阵有一些有趣的性质,不妨展开讲一讲。
一个图拟阵的对偶拟阵的意义是从图中删去一些边,但是图仍然联通。
一个图拟阵的对偶拟阵是一个图拟阵当且仅当原来的图是平面图,而且对偶拟阵对应的图对应的是平面图的任一平面对偶图。
对这个命题感兴趣的同学请阅读论文 W. T. Tutte.(1959).Matroids and graphs. tran(3), doi:10.1090/S0002-9947-1959-0101527-3.
5.2 拟阵并
5.2.1 拟阵并
我们有 \(k\) 个拟阵为 \(\mathcal M_i = \langle X_i, \mathcal I_i\rangle\)。
定义 \(X = \bigcup _{i=1}^k X_i\),\(\mathcal I = \left \{\bigcup _{i=1}^k S_i | S_i \in \mathcal I_i\right \}\)。(比如:\(k=2\) 时,\(\mathcal I = \{S_1 \cup S_2 | S_1 \in \mathcal I_1, S_2 \in \mathcal I_2\}\))
Lemma 5.2.2
【定义】拟阵并 \(\mathcal M_1 \lor \mathcal M_2 \lor \ldots \lor \mathcal M_k = \langle X, \mathcal I \rangle\)。
【引理】\(\mathcal M = \mathcal M_1 \lor \mathcal M_2 \lor \ldots \lor \mathcal M_k\) 的秩函数为
\]
Proof.
【引理 A】\(\hat {\mathcal M} = \langle \hat{X}, \hat{\mathcal I}\rangle\) 是一个拟阵,且 \(\hat{\mathcal M} = \hat{\mathcal M_1} \lor \hat{\mathcal M_2} \lor \ldots \lor \hat{\mathcal M_k}\),其中 \(\hat{\mathcal M_i} = \langle \hat {X_i}, \hat {\mathcal I_i}\rangle\),且对于任意 \(i \neq j\) 有 \(X_i \cap X_j = \varnothing\)。则对于任何 \(f:\hat X \mapsto X\),\(\langle X, \mathcal I \rangle\) 是一个拟阵,其中 \(\mathcal I = \{f(\hat I) | \hat I \in \hat{\mathcal I}\}\)。并且其秩函数是 \(r_\mathcal M(S) = \min _{T \subseteq S} [r_{\hat{\mathcal M}}(f^{-1}(T))+|S \setminus T|]\)。
Proof. 首先,\(X\) 是有穷集是显然的。
令 \(I \in \mathcal I\),则一定存在 \(\hat I \in \hat {\mathcal I}\) 使得 \(|I| = |\hat I|\) 并且 \(I = f(\hat I)\)。\(I\) 的任一子集一定可以表示为 \(f(\mathcal{\hat I}\) 的某个子集\()\)。所以 \(\langle X, \mathcal I \rangle\) 满足拟阵的遗传性。
令 \(J \in \mathcal I\), \(J = f(\hat J)\),\(\hat J \in \mathcal {\hat I}\),\(|J| = |\hat J| > |I|\),则存在 \(e \in \hat J \setminus \hat I\) 使得 \(\hat I \cup \{e\} \in \hat{\mathcal I}\)。\((1)\)
我们进一步假设 \(\hat I = \arg \max _{\hat I} |\hat I \cap \hat J|\)(在使得 \(|I| = |\hat I|\) 并且 \(I = f(\hat I)\) 的 \(\hat I\) 中选择)。
然后假设 \(f(e) \in I \cap J\),则 \(\exists e' \in \hat I \setminus \hat J\) 使得 \(f(e')=f(e)\)。
令 \(\hat I' = \hat (I \setminus \{e'\}) \cup \{e\}\),根据 \((1)\) 式可得 \(\hat I' \in \hat{\mathcal I}\),并且 \(f(\hat I')=I\)。
但是 \(|\hat I' \cap \hat J| = |\hat I \cap \hat J| + 1\),所以和 \(\hat I = \arg \max _{\hat I} |\hat I \cap \hat J|\) 矛盾。
所以 \(f(e) \notin I\)。所以存在 \(z \in J \setminus I\),也就是说 \(z = f(e)\) 使得 \(I + z \in \mathcal I\)。所以 \(\langle X, \mathcal I \rangle\) 满足拟阵的交换性质。
接下来来证明这个秩函数。
令关于 \(S\) 的划分拟阵 \(\mathcal M' = \langle \hat X, \mathcal I_p \rangle\),其中 \(\mathcal I_p = \{I \subseteq \hat X : |f^{-1}(e) \cap I| \leq 1\ \forall e \in S, |f^{-1}(e) \cap I| = 0\ \forall e \notin S\}\)。
显然,其秩函数为 \(r_{\mathcal M'}(T) = |\{e \in S : f^{-1}(e) \cap T \neq \varnothing\}|\)。
\(I\) 是一个独立集当且仅当存在子集 \(\hat I \subseteq \hat S = f^{-1}(S)\) 在 \(\mathcal M_p\) 和 \(\mathcal M'\) 中均独立。
所以 \(\max_{I \subseteq S, I \in \mathcal I} |I| = \max _{\hat I \subseteq \hat S, \hat I \in \hat {\mathcal I} \cap \mathcal I_p} |\hat I|\)。
根据 Min-Max 方程我们有 \(r_\mathcal M(S) = \min _{\hat T \subseteq \hat S} \left [r_{\mathcal {\hat M}}(\hat T) + r_{\mathcal M_p}(\hat S \setminus \hat T) \right]\)。
假设 \(\hat T = f^{-1}(T)\) 不是最优。定义 \(\hat T' = \hat S \setminus f^{-1}(f(\hat S \setminus \hat T)) = f^{-1}(S \setminus f(\hat S \setminus \hat T))\)。分类:
- 当 \(\hat T' \subseteq \hat T\) 时 \(r_{\mathcal{\hat M}}(\hat T') \leq r_{\mathcal {\hat M}}(\hat T)\),与 \(r_\mathcal M(S) = \min _{\hat T \subseteq \hat S} \left [r_{\mathcal {\hat M}}(\hat T) + r_{\mathcal M_p}(\hat S \setminus \hat T) \right]\) 矛盾。
- 当 \(r_{\mathcal M_p}(\hat S \setminus \hat T') = r_{\mathcal M_p}(\hat S\setminus \hat T)\) 时,不劣于原方案,矛盾。
- 当 \(\hat T' = f^{-1}(S \setminus f(\hat S \setminus \hat T))\) 时,不劣于原方案,矛盾。
所以 \(\hat T = f^{-1}(T)\) 一定是最优的。所以 \(r_\mathcal M(S) = \min _{T \subseteq S} \left[r_{\mathcal{\hat M}}(f^{-1}(T)) + |S \setminus T|\right]\)。\(\square\)
接下来回到引理 5.2.2。如果 \(X_i\) 满足不交,那么根据引理 A,原命题显然成立。
否则,我们通过以下步骤将其转换为 \(X_i\) 不交的情况。
- 给集合中的元素标上拟阵的序号,使其不重复,构造拟阵 \(\hat{\mathcal M} = \langle \hat X_i, \mathcal I_i\rangle\)。方法:把 \(e \in X_i\) 变成二元组 \((i,e)\)。
- 定义 \(f : \hat X \mapsto X\),\(f((i, e))=e\)。
所以我们可以得到一个不会有元素重复的 \(\hat X\)。
根据引理 A,我们有
r_{\mathcal M}(S) &= \min _{T \subseteq S} [r_{\mathcal{\hat M}}(f^{-1}(T))+|S \setminus T|] \\
&= \min _{T \subseteq S} \left[\sum _{i=1} ^k r_{\mathcal{\hat M}}(f^{-1}(T) \cap \hat X_i ) + |S \setminus T|\right]
\end{aligned}
\]
\(\square\)
5.2.3 验证独立性(拟阵交)
如何查询拟阵并里面一个集合是否独立呢?
我们可以简单地考虑我们在证明引理 A 的时候构造的划分拟阵。只要我们能够查询 \(f^{-1}\),我们就可以使用拟阵交算法求出这个划分拟阵,然后在这个划分拟阵中验证这个集合的独立性。
我们注意到这个划分拟阵中的 Ground set 的大小是求并的所有拟阵的 Ground set 的大小之和,所以这个拟阵交的方法可能效率比较低。
5.2.4 验证独立性(拟阵划分)
我们在上一个部分中已经提到了,使用拟阵交进行拟阵并中的集合独立性验证是比较低效的,所以我们在这个部分中尝试给出一种比较高效的方法。
拟阵划分的意思是对于一个拟阵并 \(\mathcal M = \mathcal M_1 \cup \mathcal M_2 \cup \ldots \cup \mathcal M_k\) 中的独立集 \(I \in \mathcal I\),\(I\) 可以表示为划分 \(I_1 \cup I_2 \cup \ldots \cup I_k\),其中 \(I_i \in \mathcal I_i\)。给定 \(s \notin I\),判断 \(I \cup \{s\}\) 是否独立。
我们可以用拟阵划分很容易的判断拟阵并中某一个集合是否独立。
我们仍然考虑交换图。每一个拟阵的交换图 \(\mathcal D_i(I_i)\) 是一个二分图,左边是 \(I_i\),右边是 \(X_i \setminus I_i\)。左边的点 \(y\) 到右边的点 \(x\) 有一条有向边当且仅当 \(I_i \setminus \{y\} \cup \{x\} \in \mathcal I_i\)。
然后我们还是仿照拟阵交的做法把这些交换图合并,合并后的图记为 \(\mathcal D\)。
定义 \(F_i = \{x \in X_i \setminus I_i | I_i \cup \{x\} \in \mathcal I_i\}\),即可以加到 \(I_i\) 中不会破坏独立性的元素的集合。
下面的定理会说明这么做如何解决拟阵划分问题。
Theoreom 5.2.5
\(\forall s \notin I\),\(I \cup \{s\} \in \mathcal I\) 当且仅当 \(\mathcal D\) 中存在一条从 \(F\) 到 \(s\) 的路径。
Proof. 先证明充分性(\(\Leftarrow\)):假设路径为 \(P\),路径 \(P\) 上的节点分别为 \(s_0, s_1, \ldots, s_p\)。
因为 \(s_0 \in F\),所以我们不妨假设 \(s_0 \in F_1\)。
我们令路径 \(P\) 中属于 \(\mathcal D_{\mathcal M_j}(I_j)\) 的边的终点集合为 \(S_i\)。
我们令 \(I_1' = (I_1 \triangle S_1) \cup \{s_0\}\)。 其中 \(\triangle\) 表示对称差,即 \(A \triangle B = (A \setminus B) \cup (B \setminus A)\)。对于 \(j>1\),我们令 \(I_j' = I_j \triangle S_j\)。
显然, \(\bigcup I_j' = I \cup \{s\}\)。所以拟阵并中 \(I \cup \{s\}\) 独立就等价于对于每个 \(j\),\(I_j' \in \mathcal I_j\)。
我们假定 \(P\) 是最短路径。(显然,如果存在一条或多条路径,那么必然存在一条最短路径)所以对于 \(j>1\) 在 \(\mathcal D_{\mathcal M_j}(I_j)\) 中在删除和加入的点之间存在一个唯一的完美匹配。(为什么会删除和加入?因为我们要把原来的变成 \(I_j'\))
所以 \(I_j' \in \mathcal I_j\)。
同理,因为 \(s_0 \in F_1\),所以 \(I_1' \in \mathcal I_1\)。必要性证毕。
顺便说一句,这个算法是多项式时间复杂度的,他只需要执行 \(\sum _i (|I_i|)(|X_i| - |I_i|)\) 次 Oracle 询问就可以了。
然后证明必要性(\(\Rightarrow\)):假设没有这么一条路径。我们令 \(T\) 是 \(\mathcal D\) 中可以到达 \(s\) 的节点的集合,则 \(F \cap T = \varnothing\)。
对于所有 \(i\),我们有 \(|I_i \cap T| = r_i(X_i \cap T)\)。所以 \(I_i \cap T\) 是 \(\mathcal M_i\) 中 \(T\) 的最大子集。
假设存在矛盾。
因为 \(|I_i \cap T| = r_i(I_i \cap T) \le r_i(X_i \cap T)\),所以只能 \(|I_i \cap T| < r_i(X_i \cap T)\)。
所以存在 \(x \in T \cap (X_i \setminus I_i)\) 使得 \((I_i \cap T) \cup \{x\} \in \mathcal I_i\)。
但是 \(x \notin F\)(因为 \(x \in T\))所以 \(I_i \cup \{x\} \notin \mathcal I_i\)。
因为 \(I_i \cup \{x\}\) 包含一个唯一的圈,所以一定存在 \(y \in I_i \setminus T\) 使得 \(I_i \setminus \{y\}\cup \{x\} \in \mathcal I_i\)。
那么 \((y,x)\) 这条边一定在 \(\mathcal D_{\mathcal M_i}(I_i)\) 中,也就是说 \(y \in T\),与 \(y \in I_i \setminus T\) 矛盾。
所以对于所有的 \(i\) 我们有 \(|I_i \cap T| = r_i(T \cap X_i)\)。
因为 \(s \in T\),我们有 \((I \cup \{s\}) \cap T = (\bigcup I_i \cup \{s\})\cap T = \bigcup(I_i \cap T) \cup \{s\}\)。
然后我们根据两个拟阵的交的秩函数,我们可以得到
r_\mathcal M(I \cup \{s\}) &\leq \left[|(I \cup \{s\} \setminus T| + \sum _{i=1} ^k r_i(T \cap X_i)\right] \\
&\leq |(I \cup \{s\}) \setminus T| + \sum _{i=1}^k |I_i \cap T| \\
&=|I \setminus T| + \sum _{i=1}^k |I_i \cap T| \\
&=|I| < |I \cup \{s\}|
\end{aligned}
\]
所以 \((I \cup \{s\}) \notin \mathcal I\),证毕。
\(\square\)
5.2.6 拟阵并的其他应用(再谈拟阵的基)
5.2.6.1 基交换定理
\(\mathcal M = \langle X, \mathcal I \rangle\) 是一个任意拟阵,\(B_1, B_2 \in \mathcal B\),对于任意划分 \(B_1 = X_1 \dot \cup Y_1\),存在划分 \(B_2 = X_2 \dot \cup Y_2\) 使得 \(X_1 \cup Y_2 \in \mathcal B\) 并且 \(X_2 \cup Y_1 \in \mathcal B\)。
Proof. 令 \(\mathcal M_1 = \mathcal M \setminus Y_1\),\(\mathcal M_2 = \mathcal M \setminus X_1\)。
显然,\(X_1 \in \mathcal I_1\),\(Y_1 \in \mathcal I_2\)。所以 \(B_1\) 在 \(\mathcal M_1 \cup \mathcal M_2 = \langle X, \mathcal I_1 \cup \mathcal I_2 \rangle\) 中是独立的。则我们只需要证明 \(B_2\) 独立就行了,那样我们就能划分 \(B_2\)。
我们只需要计算
\]
注意到,对于任意 \(A \subseteq X \setminus Y_1\),我们有 \(r_{\mathcal M_1}(A) = r_\mathcal M(A \cup Y_1) - r_\mathcal M(Y_1)\)。所以
\]
我们在 \(r_\mathcal M(U \cup Y_1) + r_\mathcal M(U \cup X_1)\) 上面用一次次模性得
\]
因为 \(r_\mathcal M(U) = |U|\) 并且 \(r_\mathcal M(U \cup X_1 \cup Y_1) = |X_1| + |Y_1|\),所以我们可以得到
\]
所以 \(r_{\mathcal M_1 \cup \mathcal M_2}(B_2) = |B_2|\),证毕。
\(\square\)
5.2.6.2 同一个拟阵的并
我们考虑 \(k\) 个一样的拟阵的并。他的秩函数是
\]
因为 \(r_{\mathcal M^k}(U)\) 仅仅是 \(U_1, U_2, \ldots, U_k \subseteq U\) 的并的最大大小,其中 \(U_i \in \mathcal I\),我们可以得到以下两个结论。
5.2.6.3 拟阵基覆盖 Matroid base covering
一个拟阵能被 \(k\) 个基覆盖当且仅当 \(\forall T \subseteq X : |T| \leq k \cdot r_\mathcal M(T)\)。
能被覆盖等价于 \(r_{\mathcal M^k}(X) = |X|\)。
5.2.6.4 拟阵基压缩 Matroid base packing
这个翻译不准确!如果有知道的同学联系我!
说句闲话,这个名字好奇怪啊,怎么翻译啊
一个拟阵包含 \(k\) 个不交的基当且仅当 \(\forall T \subseteq X : |X \setminus T| \geq k(r_\mathcal M(S) - r\mathcal M(T))\)。
有 \(k\) 个不交的基等价于 \(r_{\mathcal M^k}(X) = k \cdot r_\mathcal M(X)\)。
当拟阵是图拟阵的时候会怎么样呢?
5.2.6.5 Nash-Williams 定理
一个图 \(G\) 能被 \(k\) 个生成树覆盖当且仅当 \(\forall U \subseteq B : |E(U)| \leq k(|U| - 1)\)。
5.2.6.6 Tutte 定理
定义 \(\delta(V_1, V_2, \ldots, V_p) = \{(u,v) \in X | u \in V_i, v \in V_j, i \ne j\}\)。
一个图 \(G\) 包含 \(k\) 个边不交的生成树当且仅当对于所有的 \(V\) 的划分 \((V_1, V_2, \ldots, V_p)\),\(|\delta(V_1, \ldots, V_p)| \geq k(p - 1)\)。
下一部分将围绕这个结论展开。
Part 6. Shannon 开关游戏
这是一个经典的问题,已经有人把他的一部分搬到算法竞赛中了,如果你想要在 OJ 上面提交这道题,他的题号是 UVA 12370。(远古时期洛谷也有【模板】Shannon 开关游戏,但是那个提后来撤掉了,可能是因为假掉了?)
6.1 问题描述
有一张无向图和两个点 \(u\) 和 \(v\),两个人 Cut 和 Join 在图上玩游戏,两个人轮流操作。Cut 可以从 \(G\) 中删除一条边,而 Join 可以固定一条边使 Cut 不能删除这条边。如果一条从 \(u\) 到 \(v\) 的路径中的边都被固定了,则 Join 胜利。如果 Join 无法胜利,则 Cut 胜利。
因为这个游戏中每一次操作都比不操作有利,所以肯定会有三种结果:
- Join Game:无论谁先手都是 Join 胜利。
- Cut Game:无论谁先手都是 Cut 胜利。
- Neutural Game:谁先手谁胜利。
其实这个游戏也可以在其他的拟阵上面做,Lehman 提供了这个问题的各种策略,见 A. Lehman, “A solution to Shannon’s switching game”,J. Soc. Indust. Appl. Math.,12, 687–725, 1964. 这篇论文。
他对于图拟阵上的游戏,在 \(u\) 和 \(v\) 上面增加一条两人都不能操作的边 \(e\),令 \(X' = X \cup \{e\}\)。
这样在任何一种拟阵中,Join 想要在 \(\mathcal M\) 形成一个包含 \(e\) 的圈,Cut 想要在 \(\mathcal M^*\) 即对偶拟阵中形成一个包含 \(e\) 的圈。
Edmonds 考虑了这个问题的一个更加一般化的形式。对于拟阵 \(\mathcal M = \langle N \dot \cup K, \mathcal I\rangle\),两个人在 \(N\) 上面进行游戏。如果 Join 得到了一个集合 \(A \subseteq N\) 使得 \(\operatorname{span}(A) \supseteq K\),则 Join 胜利。
这个问题的一个特例是 \(K\) 的 span 包括整个 ground set。那么此时 Join 就想要得到一个基。(这个特例对应了 5.2.3 中的特例)
当拟阵是一个图拟阵的时候,Join 就想要得到一个生成树。
6.2 特例下的 Shannon 开关游戏
上述特例下,一个拟阵 \(\mathcal M = \langle X, \mathcal I \rangle\) 是一个 Join Game 当且仅当 \(\mathcal M\) 有两个不交的基。
Proof. 先证 \(\Leftarrow\)。假设 \(M\) 包含两个不交的基。我们现在要构造 Join 后手的必胜策略。
令 \(B_1\),\(B_2\) 是 \(\mathcal M\) 中的不交的基。如果 Cut 删除不在 \(B_1\) 或者 \(B_2\) 中的元素,那么没有一点问题。否则 Join 就要在 \(B_2\) 中找到一个 \(y\) 使得 \(B_1 \setminus \{x\} \cup \{y\} \in \mathcal B\)。(根据基交换定理)
接下来 Join 就要在 \(\mathcal M \setminus \{y\}\) 中找到一个基。显然,\(B_1 \setminus \{x\}\) 和 \(B_2 \setminus \{y\}\) 是新的拟阵中的不交的基。
归纳可得 Join 后手时也有必胜策略。先手时的必胜策略是显然的。
然后证明 \(\Rightarrow\)。
假设 \(\mathcal M\) 没有两个不交的基。我们现在要构造 Cut 先手时的必胜策略。
根据拟阵基压缩定理,存在 \(T \subseteq X\) 使得 \(|X \setminus T| < 2(r_\mathcal M(X) - r_\mathcal M(T))\)。Cut 操作时 Cut 总是在 \(X \setminus T\) 中操作。因为 Cut 先手,所以 Cut 会删除 \(X \setminus T\) 的至少一半。所以 Join 固定的所有元素的秩会严格小于 \(r_\mathcal M(T) + (r_\mathcal M(X) - r_\mathcal M(T)) = r_\mathcal M(X)\),即 Join 不能固定一个基。
\(\square\)
6.3 一般情况的 Shannon 开关游戏
Theoreom 一个拟阵是一个 Join Game 当且仅当 \(\exists A,B \subseteq S\) 使得 \(A \cap B = \varnothing\),并且 \(e \in \operatorname{span}_\mathcal M(A) = \operatorname{span}_\mathcal M(B)\)。
\(\Leftarrow\) 的证明应该不难,这个和特例下的情况差不多,这里大概用通俗一点的话再说一下思路。Join 的必胜策略在于找到 \(A \cup B\) 中的元素或者 \(A\) 和 \(B\) 中最大独立子集中的元素(忽略其他的使得最大独立子集成为基)。如果 Cut 删掉了想要固定的边 \(x\) 就再找一个 \(y\) 替上。根据基压缩定理,替换之后的仍然是不交的基,所以我们可以直接归纳证明。\(\square\)
我们让 Cut 在对偶拟阵上面玩。令 Cut 选择的元素的集合为 \(\mathscr C\),Join 选择的元素是 \(\mathscr J\)。那么如果 Cut 满足了 \(e \in \operatorname{span}_{\mathcal M^*}(\mathscr C)\) 他就赢了;如果 Join 满足了 \(e \in \operatorname{span}_{\mathcal M}(\mathscr J)\) 他就赢了。
Lemma A 若 \(C \in \mathcal C_\mathcal M\),\(D \in \mathcal C_{\mathcal M^*}\),则 \(|C \cap D| \neq 1\)
假设存在 \(C \in \mathcal C_\mathcal M\),\(D \in \mathcal C_{\mathcal M^*}\) 使得 \(|C \cap D| = 1\) 。令 \(C \cap D = \{e\}\)。
因为 \(D \setminus \{e\} \in \mathcal I_{\mathcal M^*}\),所以 \(X' \setminus (D \setminus \{e\})\) 包含一个基。
因为 \(C \setminus \{e\} \subset X' \setminus (D \setminus \{e\})\),并且 \(C \setminus \{e\} \in \mathcal I_\mathcal M\),所以我们不难得到存在一个基 \(B\) 使得 \(C \setminus \{e\} \subset B \subset X' \setminus (D \setminus \{e\})\)。
如果 \(e \in B\) 则 \(C \subseteq B\),与 \(B\) 是一个基矛盾。
所以 \(C \setminus \{e\} \subseteq B \subseteq X' \setminus (D \setminus \{e\})\),即 \(D \subseteq X' \setminus B\)。所以 \(D\) 在对偶拟阵中就独立了,矛盾。
所以 \(|D \cap C| \neq 1\)。
\(\square\)
Lemma B 如果我们让 Cut 在对偶拟阵上面玩,则正好有一个玩家能胜利。
Proof.
如果存在两个人同时胜利的情况,则 \(\exists \mathscr J, \mathscr C \subset S\) 使得 \(\mathscr J \cap \mathscr C = \varnothing\),\(\mathscr J \cup \mathscr C = X\),\(e \in \operatorname{span}_\mathcal M(\mathscr J)\) 并且 \(e \in \operatorname{span}_{\mathcal M^*}(\mathscr C)\)。所以存在圈 \(C \subseteq \mathscr J \cup \{e\}\) 和对偶拟阵上的圈 \(D \subseteq \mathscr C \cup \{e\}\) 使得 \(C \cap D = \{e\}\),与 Lemma A 矛盾。
如果 Join 输了,那么 \(e \notin \operatorname{span}(\mathscr J) \implies r(\mathscr J \cup \{e\}) = r(\mathscr J) + 1\),所以 \(r_{\mathcal M^*}(\mathscr C) = |\mathscr C| + r(X' \setminus \mathscr C) - |X'| = |\mathscr C| + r(\mathscr J \cap \{e\}) - |X'| = |\mathscr C| + r(\mathscr J) + 1 = |\mathscr C \cup \{e\}| + r(\mathscr J) - |X'| = r_{\mathcal M ^*}(\mathscr C \cup \{e\}) \implies e \in \operatorname{span}(\mathscr C)\),所以 Cut 赢了。
\(\square\)
于是我们不难得到我们构造的对称游戏和原来的游戏是等价的。
顺便说一句,既然是对称的游戏,Cut Game 的条件应该和 Join Game 的条件是相应的,所以 Cut Game 的条件是 \(\exists A,B \subseteq S\) 使得 \(A \cap B = \varnothing\),\(e \in \operatorname{span}_{\mathcal M^*}(A) = \operatorname{span}_{\mathcal M^*}(B)\)。
我们回忆一下拟阵基压缩性质,当 \(k=2\) 的时候,存在两个不交的基的条件是 \(\forall U \subseteq X'\) 满足 \(|X' \setminus U| \geq 2(r(X') - r(U))\)。这个显然也可以表示为:
- \(\forall U \subseteq X'\) 满足 \(2r(U) - |U| \geq 2r(X') - |X'|\)
- \(2r(X') - |X'| = \min _{U \subseteq X'}(2r(U) - |U|)\)
- \(U = X'\) 时 \(g(U) = 2r(U) - |U|\) 取到最小值
(命题 C) 所以我们不难得到对于 \(F \subseteq X'\) 存在 \(A, B\) 使得 \(A \cap B = \varnothing\) 并且 \(F = \operatorname{span}(A) = \operatorname{span}(B)\),当且仅当 \(2r(F) - |F| = \min _{U \subseteq F}(2r(U) - |U|)\)。
因为 \(r(U)\) 具有次模性,\(|U|\) 具有模性,所以 \(g(U)\) 也具有次模性。
Lemma D 令 \(\mathcal L = \{S \subseteq X' : 2r(S) - |S| = \min _{U \subseteq X'}(2r(U) - |U|)\}\)。则若 \(A,B \in \mathcal L\) 则 \(A \cup B \in L\),\(A \cap B \in L\)。
Proof. 因为 \(g(U)\) 具有次模性,所以 \(2 \min _{U \subseteq X'}(2r(U) - |U|) = (2r(A) - |A|) + (2r(B) - |B|) \geq (2r(A \cap B) - |A \cap B|) + (2r(A \cup B) - |A \cup B|)\)。所以 \(2r(A \cap B) - |A \cap B| = 2r(A \cup B) - |A \cup B| = \min _{U \subseteq X'}(2r(U) - |U|)\)。所以 \(A \cap B\) 和 \(A \cup B\) 都在 \(\mathcal L\) 中。
\(\square\)
令 \(\hat X = \arg \min _{U \subseteq X}(2r(U) - |U|)\)。
根据命题 C,我们可以得到:
\]
因为 \(r_{\mathcal M^*}(U) = |U| + r(X' \setminus U) - r(X')\),所以
\]
所以 \(U\) 使 \(2r_{\mathcal M^*}(U) - |U|\) 取到最小值当且仅当 \(X' \setminus U\) 使 \(2r(U) - |U|\) 取到最小值。
Lemma E 如果 \(e \notin \operatorname{span}(\hat X)\) 则 \(\forall Y \subseteq X'\) 有 \(2r(\hat X) - |\hat X| \leq 2r(Y) - |Y|\)。
Proof. 假设存在 \(Y\) 使得 \(2r(\hat X) - |\hat X| ? 2r(Y) - |Y|\)。
根据 \(\hat X\) 的定义我们不难得到 \(e \in Y\),并且 \(2r(Y \setminus \{e\}) - |Y \setminus \{e\}| \geq 2r(\hat X) - |\hat X| > 2r(Y) - |Y|\)。
因为 \(1 > 2r(Y) - 2r(Y \setminus \{e\}\),所以 \(r(Y) = r(Y \setminus \{e\})\)。
所以 \(2r(Y \setminus \{e\}) - |Y \setminus \{e\}| = 2r(\hat X) - |\hat X|\),并且 \(Y \setminus \{e\} \subseteq \hat X\)。
但是 \(e \in \operatorname{span}(Y \setminus \{e\})\),所以 \(e \in \operatorname{span}(\hat X)\),矛盾。
\(\square\)
根据命题 C,存在两个 \(X' \setminus \hat X\) 的子集满足 \(\operatorname{span}_{\mathcal M^*}(A) = \operatorname{span}_{\mathcal M^*}(B) = X' \setminus \hat X \ni e\)。
所以如果 \(e \notin \operatorname{span}(\hat X)\),Cut 作为先手有必胜策略。(Cut 可以像 Join 的必胜策略那样玩,先手保证其必胜)
\(\square\)
因为必胜策略并不依赖于 \(e\),所以他们并不需要提前知道 \(e\)。
6.4 Shannon 开关游戏的玩法
这里只介绍图拟阵上面 Shannon 开关游戏怎么玩。因为这是一个次模性函数最小值的问题,其他拟阵的该问题我不太会。感兴趣的读者可以看看这篇论文:S. Thomas McCormick. Submodular Function Minimization[J]. Handbooks in Operations Research and Management Science,2005,12
为了输出具体的操作,我们需要计算 \(\hat X\)。
我们令选出的集合为 \(U\)。记 \(U\) 连接的节点集合是 \(S\),则如果 \(\hat X = U\) 则 \(r(U)\) 一定为 \(|S| - 1\),并且 \(U\) 为一个导出子图,记为 \(E(S)\)。
所以我们需要找使得 \(2|S| - 2 - |U|\) 最小的 \(S\)。
这个显然可以用最小割来解决。构造一个图,图中的点是 \(V \cup \{s, t\}\),其中 \(s,t\) 是源点和汇点,边是
- 对于原图中有的边 \((u,v)\),我们使 \((u,v)\) 和 \((v,u)\) 的容量为 1。
- 令 \(P = \{v \in V | |\delta(v)| > 4\}\),\(N = \{v \in V | |\delta(v)| < 4\}\)。对于 \(v \in P\),有容量为 \(|\delta(v)| - 4\) 的边 \((v, t)\);对于 \(v \in N\),有容量为 \(4 - |\delta(t)|\) 的边 \((s, v)\)。
考虑图中 \(U \cup \{s\}\) 和 \((V \setminus U) \cup \{t\}\) 分开的某一个割。他的容量:
&|\delta(U)| + \sum _{v \in U \cap P} (|\delta(v)| - 4) + \sum _{v \in N \setminus U} (4 - |\delta(v)|) \\
&= |\delta(U)| + \sum _{v \in V \setminus U} (4 - |\delta(v)|) + \sum_{v \in P} (|\delta(v)| - 4) \\
&= 4|V \setminus U| - 2|E(V \setminus U)| + \sum _{v \in P} (|\delta(v)| - 4)
\end{aligned}
\]
所以最小化 \(2|S| - |U|\) 相当于一个最小割。
我们考虑枚举 \(i \in V\),然后找到 \(s\) 和 \(i,t\) 之间的最小割。
最大流即可,为了找到方案可以在残量网络中找到 \(s\) 可达的节点。
Part 7. 例题
这一部分是一些关于拟阵的可以在 OJ 上面提交的题目。
7.1 最小生成树
各大 OJ 上面的最小生成树模板题都可以交,这里就不贴出链接了。
本题解法见【3.2 带权的一般情况 & 重温 Kruskal 算法】,代码同 Kruskal 算法的代码。
7.2 无向图方向问题
(我觉得这个经典问题应该网上有,但是我没找到,知道的同学联系我
给定一张无向图,你需要给边标上方向,使得点 \(v\) 的入度小于等于 \(k_v\)。
不知道你看到这个问题是否立刻想到网络流,但是其实这个问题也可以用拟阵交解决。
考虑每条无向边都变成两条有向边之后用拟阵交求解。
构造两个划分拟阵,即:
\mathcal M_2= \langle E, \mathcal I_2= \{F:|F \cap \delta^-_v| \le k_v\rangle
\]
其中 \(\delta^-\) 表示入边。
算出两个拟阵的交就可以了。
7.3 Game of connect
是 Shannon 开关游戏问题的简化版。
讲解可以看 Part 6,这里直接上代码。
int n, m, to[M], head[N], p[N], nxt[M], vis[M], dep[N], dis[M], pre[M];
bool in[M], v1[M], v2[M];
std::queue<int> Q;
int dfs(int u)
{
int low = dep[u];
for (int e = head[u]; e != -1; e = nxt[e])
if (!vis[e >> 1])
{
vis[e >> 1] = 1;
int v = to[e];
if (~dep[v])
{
cmin(low, dep[v]);
v1[e >> 1] = 1;
}
else
{
dep[v] = dep[u] + 1;
int tmp = dfs(v);
cmin(low, tmp);
v1[e >> 1] = tmp <= dep[u];
}
}
return low;
}
bool augment()
{
memset(v2, 0, sizeof(v2));
memset(head, -1, sizeof(head));
for (int i = 0; i < m << 1; ++i)
if (!in[i >> 1])
{
nxt[i] = head[to[i ^ 1]];
head[to[i ^ 1]] = i;
}
memset(vis, 0, sizeof(vis));
memset(dep, -1, sizeof(dep));
dep[0] = 0;
dfs(0);
dsu.init(n);
for (int i = 0; i < m << 1; ++i)
if (in[i >> 1])
dsu.merge(to[i], to[i ^ 1]);
memset(dis, -1, sizeof(dis));
while (!Q.empty())
Q.pop();
for (int i = 0; i < m; ++i)
if (!in[i])
{
v2[i] = dsu.find(to[i << 1]) != dsu.find(to[i << 1 | 1]);
if (v2[i])
dis[i] = 0, pre[i] = -1, Q.push(i);
}
while (!Q.empty())
{
int u = Q.front();
Q.pop();
if (!in[u] && v1[u])
{
while (~u)
in[u] ^= 1, u = pre[u];
return 1;
}
if (in[u])
{
dsu.init(n);
for (int i = 0; i < m; ++i)
if (in[i] && i != u)
dsu.merge(to[i << 1], to[i << 1 | 1]);
for (int v = 0; v < m; ++v)
if (!in[v] && dis[v] == -1 && dsu.find(to[v << 1]) != dsu.find(to[v << 1 | 1]))
dis[v] = dis[u] + 1, pre[v] = u, Q.push(v);
}
else
{
dsu.init(n);
int comp = n;
for (int i = 0; i < m; ++i)
if (!in[i] && i != u)
comp -= dsu.merge(to[i * 2], to[i * 2 + 1]);
for (int v = 0; v < m; ++v)
if (in[v] && dis[v] == -1 && (comp == 1 || (comp == 2 && dsu.find(to[v * 2]) != dsu.find(to[v * 2 + 1]))))
dis[v] = dis[u] + 1, pre[v] = u, Q.push(v);
}
}
return 0;
}
bool mian()
{
scanf("%d%d", &n, &m);
dsu.init(n);
for (int i = 0; i < m; ++i)
{
scanf("%d%d", &to[i * 2], &to[i * 2 + 1]);
dsu.merge(to[i * 2], to[i * 2 + 1]);
}
for (int i = 1; i < n; ++i)
if (dsu.find(0) != dsu.find(i))
return 0;
memset(in, 0, sizeof(in));
int res = 0;
while (augment())
++res;
return res == n - 1;
}
7.4 Seollao
有一个 \(n \times m\) 的网格图,一些格子里面有石头,剩下的格子是空着的。我们定义一个格子的邻居为其上下左右的格子所。我们把每个格子都黑白染色,染色方案为:左上角的格子 \((1,1)\) 是黑色的,每一个格子的颜色必须和他的邻居的颜色不同。
你可以在相邻的格子之间放一些墙。如果两个格子之见有一堵墙,则这两个格子将不再是邻居。迷宫必须满足以下性质:
- 对于任意两个空闲的格子,存在且仅存在一条简单路径(简单路径即:从一个格子出发,到达另一个格子,经过的格子不重复,且不能撞墙)
- 一开始的时候,孩子们会都待在 \((1,1)\),然后到一些格子里面躲藏。这些格子必须满足他们是空闲的,并且他们只有一个空闲的邻居。
- 孩子们只能在白色格子里面躲藏。
输入这个花园的地图,输出符合要求的迷宫。
题目中所说的“只有一条简单路径”,即我们需要构造一棵生成树,且要满足叶节点的颜色一定是白色。
我们注意到黑色的节点只与白色节点相邻,所以黑色的点集和白色的点集是 \(2\) 个独立集。
Theoreom 能找到一个无环的子图使得所有的黑点的度都为 \(2\) 是答案存在的充必条件。
Proof. 由于它是无环子图,则我们可以添上一些边让他变成一颗生成树。而树的叶子节点的度数为 \(1\),所以添边后形成的生成树是符合条件的。
如果存在答案,我们将生成树中的一些边删去,则我们一定可以得到一个无环子图使得黑点的度都是 \(2\)。\(\square\)
然后是不是就很容易解决了。
接下来我们考虑怎么处理这个问题。
我们显然可以用图拟阵 \(\mathcal M_1\) 解决无环的问题。
我们发现度数恰好为 2 是很难构造的。但是如果我们有度数 \(\le 2\),判断是否符合要求是很简单的。
我们考虑构造一个拟阵 \(\mathcal M_2 = \langle X,\mathcal I_2\rangle\),其中 \(\mathcal I_2\) 需要满足所有黑点度数 \(\le 2\) 的方案都独立。
然后直接求拟阵交就可以了。
边数为 \(\mathcal O(nm)\),所以总的时间复杂度为 \(\mathcal O(n^3m^3)\)。
上代码。
class Matroid
{
private:
const int fx[4] = {-1, 0, 0, 1};
const int fy[4] = {0, -1, 1, 0};
struct tuple
{
int x, y;
};
int n0, n1, n, m, demands;
int count[801], dist[801], prev[801], que[801];
bool vis[805], ok1[801], ok2[801];
char grid[21][21], ans[41][41];
tuple E[801];
#define make_tuple(x, y) ((tuple){x, y})
#define id(x, y) ((x)*n1 + y)
#define valid(x, y) ((x + y) > 0 && (x + y) % 2 == 0)
#define checkx(x) (x >= 0 && x < n0)
#define checky(x) (x >= 0 && x < n1)
IL void get_edges(int i, int j)
{
for (int k = 0; k < 4; ++k)
{
int u = i + fx[k], v = j + fy[k];
if (checkx(u) && checky(v) && grid[u][v] == 'O')
E[m++] = make_tuple(id(i, j), id(u, v));
}
}
bool augument()
{
dsu.init(n);
memset(count, 0, sizeof(count));
memset(dist, -1, sizeof(dist));
for (int i = 0; i < m; ++i)
if (vis[i])
{
dsu.merge(E[i].x, E[i].y);
++count[E[i].x];
}
int tail = 0;
for (int i = 0; i < m; ++i)
{
ok1[i] = !vis[i] && dsu.find(E[i].x) != dsu.find(E[i].y);
ok2[i] = !vis[i] && count[E[i].x] < 2;
if (ok1[i])
{
dist[i] = 0, prev[i] = -1, que[tail++] = i;
if (ok2[i])
{
vis[i] = true;
return true;
}
}
}
for (int head = 0; head < tail; ++head)
{
int u = que[head];
if (ok2[u])
{
while (~u)
vis[u] ^= 1, u = prev[u];
return true;
}
if (vis[u])
{
dsu.init(n);
for (int i = 0; i < m; ++i)
if (vis[i] && i != u)
dsu.merge(E[i].x, E[i].y);
for (int v = 0; v < m; ++v)
if (!vis[v] && dsu.find(E[v].x) != dsu.find(E[v].y) && dist[v] == -1)
dist[v] = dist[u] + 1, prev[v] = u, que[tail++] = v;
}
else
for (int v = 0; v < m; ++v)
if (vis[v] && count[E[u].x] - (E[u].x == E[v].x) < 2 && dist[v] == -1)
dist[v] = dist[u] + 1, prev[v] = u, que[tail++] = v;
}
return false;
}
public:
void solve()
{
n0 = io::in(), n1 = io::in();
for (int i = 0; i < n0; ++i)
io::gets(grid[i]);
n = n0 * n1, m = demands = 0;
for (int i = 0; i < n0; ++i)
for (int j = 0; j < n1; ++j)
if (grid[i][j] == 'O' && valid(i, j))
demands += 2, get_edges(i, j);
while (augument())
--demands;
if (demands)
pc('N'), pc('O'), pc('\n');
else
{
pc('Y'), pc('E'), pc('S'), pc('\n');
get_edges(0, 0);
dsu.init(n);
for (int t = 0; t < 2; ++t)
for (int i = 0; i < m; ++i)
{
bool connected = dsu.find(E[i].x) == dsu.find(E[i].y);
if (t && !connected)
vis[i] = true;
if (vis[i] && !connected)
dsu.merge(E[i].x, E[i].y);
}
for (int i = 0; i < n0 * 2 - 1; ++i)
for (int j = 0; j < n1 * 2 - 1; ++j)
ans[i][j] = ' ';
for (int i = 0; i < n0; ++i)
for (int j = 0; j < n1; ++j)
ans[i * 2][j * 2] = grid[i][j];
for (int i = 0; i < m; ++i)
if (vis[i])
{
int s = min(E[i].x, E[i].y);
int s1 = max(E[i].x, E[i].y);
if (s + 1 == s1)
ans[s / n1 * 2][s % n1 * 2 + 1] = 'i';
else
ans[s / n1 * 2 + 1][s % n1 * 2] = '!';
}
for (int i = 0; i < n0 * 2 - 1; ++i)
{
for (int j = 0; j < n1 * 2 - 1; ++j)
pc(ans[i][j]);
pc('\n');
}
}
}
};
7.5 Rainbow Graph
19. Rainbow Graph — Prime New Year Contest - 2018 Rainbow Graph – Kattis Rainbow Graph - 计蒜客
有一张有向图,每一条边有一个颜色和一个权值。颜色有 RGB 三种。要求:选出 \(k\) 条边,使得 R+G 和 B+G 的边的组合均能使图联通,并且方案的总权值最小。
对于 \(1 \le k \le m\) 都要求出答案,无解输出 -1。
我们考虑 RG / BG 的限制很讨厌,但是这两个条件又恰好是图拟阵的对偶拟阵的条件,所以我们就直接求出两个图拟阵(一个对应 R+G 的图,一个对应 B+G 的图)的带权拟阵交就可以了。
是带权拟阵交的模板题啦~
上代码。
#include <bits/stdc++.h>
const int N = 105;
class DSU
{
private:
int f[N];
public:
int components;
inline void init(int n)
{
for (register int i = 0; i < n; ++i)
f[i] = i;
components = n;
}
inline int find(int x)
{
while (x != f[x])
x = f[x] = f[f[x]];
return x;
}
inline void merge(int x, int y)
{
int fx = find(x), fy = find(y);
if (fx != fy)
f[fx] = fy, --components;
}
} dsu;
int n, m, a[N], b[N], w[N], c[N], pre[N], res[N];
int in[N], G[N][N], vis[N], ok[2][N];
std::pair<int, int> dist[N];
std::queue<int> Q;
int augment()
{
memset(ok, 0, sizeof(ok));
memset(G, 0, sizeof(G));
for (int t = 0; t < 2; ++t)
{
for (int i = 0; i < m; ++i)
if (!vis[i])
{
dsu.init(n);
for (int j = 0; j < m; ++j)
if (!vis[j] && j != i && c[j] != t)
dsu.merge(a[j], b[j]);
ok[t][i] = dsu.components == 1;
for (int j = 0; j < m; ++j)
if (vis[j])
{
int &ref = t ? G[i][j] : G[j][i];
ref = dsu.components == 1;
if (c[j] != t)
ref |= dsu.components == 2 && dsu.find(a[j]) != dsu.find(b[j]);
}
}
}
for (int i = 0; i < m; ++i)
dist[i] = {INT_MAX, INT_MAX};
memset(in, 0, sizeof(in));
for (int i = 0; i < m; ++i)
if (ok[0][i])
dist[i] = {-w[i], 1}, pre[i] = -1, in[i] = true, Q.push(i);
while (!Q.empty())
{
int u = Q.front();
Q.pop();
in[u] = false;
for (int v = 0; v < m; ++v)
{
std::pair<int, int> cur = dist[u];
cur.first += vis[v] ? w[v] : -w[v], ++cur.second;
if (G[u][v] && cur < dist[v])
{
dist[v] = cur, pre[v] = u;
if (!in[v])
in[v] = true, Q.push(v);
}
}
}
std::pair<std::pair<int, int>, int> best{std::pair<int, int>{INT_MAX, INT_MAX}, -1};
for (int i = 0; i < m; ++i)
if (ok[1][i])
best = std::min(best, std::make_pair(dist[i], i));
if (best.second == -1)
return false;
for (int u = best.second; ~u; u = pre[u])
vis[u] ^= 1;
return true;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < m; ++i)
{
char s[4];
scanf("%d%d%d%s", &a[i], &b[i], &w[i], s);
--a[i], --b[i];
if (s[0] == 'B')
c[i] = 0;
else if (s[0] == 'R')
c[i] = 1;
else
c[i] = 2;
}
memset(res, -1, sizeof(res));
res[m] = 0;
for (int i = 0; i < m; ++i)
res[m] += w[i];
memset(vis, 0, sizeof(vis));
for (int i = m; i-- && augment();)
{
res[i] = 0;
for (int j = 0; j < m; ++j)
if (!vis[j])
res[i] += w[j];
}
for (int i = 1; i <= m; ++i)
printf("%d\n", res[i]);
return 0;
}
7.6 Pick Your Own Nim
Alice 和 Bob 每个人有一些盒子,每个盒子里面有几堆石子。每个人先从自己的每个盒子里面选出一堆石子,然后 Alice 从所有选出的石子堆中选出一个非空子集,然后两个人在这个子集上玩 Nim 游戏,Bob 先手。现在给出 Alice 选出的石子和 Bob 手里盒子的情况,求一个无论 Alice 怎么选子集 Bob 都有必胜策略的选石子堆方案,没有输出 \(-1\)。
简化:不存在异或和为 \(0\) 的子集。显然我们可以把他直接变成在 \(\mathbb Z _2^{60}\) 上的独立集。
然后考虑“每个盒子只能选出一堆”的限制,所以我们把线性拟阵和有色拟阵求拟阵交就可以了。
代码以后会有的
7.7 Yet Another Binary Matrix
给你一个 \(n \times n\) 的 01 方阵,\(R\) 是行的集合,\(C\) 是列的集合。记 \(W(P,Q)\) 为一个 \(|P|\) 行 \(|Q|\) 列的矩阵,第 \(i\) 行,第 \(j\) 位和方阵中的第 \(P_i\) 行和 \(Q_j\) 列是一样的。给你一个行的集合 \(A\) 和列的集合 \(B\),找到列的集合 \(X\) 使得 \(X \cap B = \varnothing\) 并且 \(W(A, X \cup B)\) 的行是线性独立的并且 \(W(R \setminus A, C \setminus \{X \cup B\})\) 的行是线性独立的。
简化:让 \(r(W(A, X \cup B)) + r(W(R \setminus A, C\setminus \{X \cup B\})) = |W|\)。
然后直接求出线性拟阵和一个线性拟阵的对偶的交就好了。
代码以后会有的
如果还有别的拟阵交的题就和我说,比较好玩的我会加进来的
Part 8. 总结
总之,拟阵是一个强大的工具,可以解决种种其他方法难以解决(并且一眼看上去根本没思路)的问题。
感兴趣的同学可以自行百度搜索关于拟阵的更多的内容(有很多比较高深的内容)!
Thank you for your time!
从拟阵基础到 Shannon 开关游戏的更多相关文章
- iOS系列 基础篇 09 开关、滑块和分段控件
iOS系列 基础篇 09 开关.滑块和分段控件 目录: 案例说明 开关控件Switch 滑块控件Slider 分段控件Segmented Control 1. 案例说明 开关控件(Switch).滑块 ...
- C#基础:飞行棋游戏
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- unity零基础开始学习做游戏(二)让你的对象动起来
-------小基原创,转载请给我一个面子 小基认为电子游戏与电影最重要的区别就是交互,如果电子游戏没有让你输入的交互功能的话,全程都"只可远观,而不可鼓捣"的话,你可能是在看视频 ...
- unity零基础开始学习做游戏(三)鼠标输入,来个虚拟摇杆怎么样?
-------小基原创,转载请给我一个面子 现在移动游戏越来越火,大家都拿手机平板玩游戏,没有键盘和手柄输入,所以就不得不看看虚拟摇杆怎么搞?(小基对于没有实体反馈不是很喜欢呢) 首先要清楚,鼠标操作 ...
- unity零基础开始学习做游戏(五)看看你的完成度,进度条了解一下?
-------小基原创,转载请给我一个面子 上回书说道,英雄和魔王都做完了,子弹也能发射了,就是不知道啥时候能干死魔王.那小基得做个血条来展示一下,他离死不远了(•౪• ) 其实血条也可以看作是进度条 ...
- unity零基础开始学习做游戏(一)为了实现你的游戏,你需要提前做的准备工作
-------小基原创,转载请给我一个面子 正所谓,工欲善其事,必现准备好电脑.接下来跟着小基一步一步来搭建你的开发环境吧 1.下载安装unity 上面的那个是破解软件,下面是unity5.5.6的安 ...
- Python基础之猜数游戏
例题一:猜数游戏.在程序中预设一个0~9之间的整数,让用户通过键盘输入所猜的数,如果大于预设的数,显示“遗憾,太大了”:小于预设的数,显示“遗憾,太小了”,如此循环,直至猜中该数,显示“预测N次,你猜 ...
- python基础之猜数字游戏
#猜数字游戏 import random #impor语句导入random模块 guessor=0; print("#"*30) #输出30个”#“(”############## ...
- 第九章 nginx基础之搭建小游戏
一.nginx部署 1.epel源安装 [root@web01 ~]# yum install -y nginx 2.官方源安装 1.配置官方源[root@web02 ~]# vim /etc/yum ...
随机推荐
- POJ4007 Flood-it! 题解
调得我快死了啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊!!!! 先自己写了几发,老是 T,然后去看题解,大体思路居然都差不多,估计是自己写挂了orz. 几乎所有题解都有个vis数组,真 nm 看不懂到底是什么意思 ...
- DataGridView 显示行号与背景颜色
实现的方式有好几种.之前使用的是下面这种在RowPostPaint事件中实现,效率不高.每次改变控件尺寸时都会执行 private void MsgGridView_RowPostPaint(obje ...
- Python基础之tabview
以前写过界面,但是没有记录下来,以至于现在得从头学习一次,论做好笔记的重要性. 现在学习的是怎么写一个tabview出来,也就是用tkinter做一个界面切换的效果.参考链接:https://blog ...
- 解决:CannotAcquireResourceException: A ResourcePool could not acquire a resource from its primary factory or source.
log4j给出的异常信息有下面几句: Caused by: org.hibernate.exception.GenericJDBCException: Unable to acquire JDBC C ...
- GhostScript 沙箱绕过(命令执行)漏洞(CVE-2018-16509)
影响范围: Ghostscript 9.24之前版本 poc地址 https://github.com/vulhub/vulhub/blob/master/ghostscript/CVE-2018-1 ...
- SpringBoot整合Guacamole教程
前言 本文主要介绍的是SpringBoot如何整合Guacamole在浏览器是远程桌面的访问. Guacamole 介绍 Apache Guacamole 是一个无客户端远程桌面网关.它支持标准协议, ...
- Fast Run:提高 MegEngine 模型推理性能的神奇功能
作者:王博文 | 旷视 MegEngine 架构师 一.背景 对于深度学习框架来说,网络的训练/推理时间是用户非常看中的.在实际生产条件下,用户设计的 NN 网络是千差万别,即使是同一类数学计算,参数 ...
- 重定向">" 及">>"符号的简单运用
1.command > file 将输出重定向(可理解写入)到 file. 2.command >> file 将输出以追加的方式重定向到 file,也就是写入到 file的尾端. ...
- 这个 Redis 连接池的新监控方式针不戳~我再加一点佐料
Lettuce 是一个 Redis 连接池,和 Jedis 不一样的是,Lettuce 是主要基于 Netty 以及 ProjectReactor 实现的异步连接池.由于基于 ProjectReact ...
- PTui又加全景图 佳田未来城 of 安阳
今天我又拍了张360°无死角全景,因为我发现这种照片非常具有纪念意义,一个全景能胜过一千张照片. 我上一次的全景的地址:http://www.dushangself.site/dslab/?id=8 ...