拟阵笔记

拟阵是很多贪心算法的基础,也可以帮助我们验证自己的贪心算法的正确性,接下来是我从《算法导论》中整理出来的一些关于拟阵的性质:

定义

吐槽:虽然说拟阵叫拟阵,但是这个“阵”和矩阵的阵几乎一点关系都没有(名字的由来纯粹是历史遗留问题),拟阵和矩阵的关系就像JavaScript和Java,雷锋和雷峰塔一样……

拟阵:拟阵是一个二元组M = (S, I),其中S为一个有限集,IS的一个族(即子集的集合)并满足如下性质:

  1. 遗传性:B \in IA \subseteq B,则A \in I
  2. 交换性:A \in I, B \in I|A| < |B|,那么存在元素x \in B \setminus A,使得A \cup \{x\} \in I。(又是一个误导性的名字……)

I中的集合成为S独立子集

图拟阵:对于一个图G = (V, E),我们定义它的图拟阵为M_G = (S_G, I_G),当中S_G为边集,而E的子集A \in I_G的当且仅当A中无环(森林)。图拟阵与最小生成树有关(这也解释了为什么最小生成树的算法都是贪心)。由于森林的子图还是森林,因此该拟阵的遗传性显然。而该拟阵的交换性也在算法导论中有详细的证明,简单讲起来就是对于森林A, B|A| < |B|,我们知道A中有|V| - |A|棵树,B中有|V| - |B|棵树比A少,因此一定存在一条边(u, v)使得u, vA中分别属于两棵树,而在B中却在一棵树上,显然A \cup \{(u, v)\} \in I_G,证毕。

拓展:对于集合A,若存在元素x使得A \cup \{x\} \in I,则称xA的一个拓展。

最大独立子集:不存在拓展的独立子集。

定理:所有的最大独立子集等大小。

证明:反证, 假设存在最大独立子集A, B使得|A| < |B|,由交换性,必然存在x \in B \setminus AA的一个拓展,证毕。

加权拟阵:若存在一个权函数w为所有S的元素定义了严格正的权值,则称M为加权拟阵,定义独立子集A的权值为:

w(a) = \sum_{x \in A} w(x)

和贪心的关系

很多贪心问题可以转化为在拟阵上求最大权独立子集,或者称为拟阵的最优子集

例:最小生成树算法当中我们可以对于边e定义权重w(e) = l_{max} - l(e),其中l(e)为边的长度,l_{max}为一个极大的数。在图拟阵上最大化独立子集权重必然等价于在图上最小化生成树边权(因为生成树的边数总是固定的)。

求解最优子集的算法:S的所有元素x按照w(x)从大到小排序,初始化A = \emptyset,然后依次从大到小考虑每个元素x,并尽可能地x去拓展A,最后得到的集合必定是最优子集。

这个算法的贪心本质暴露无遗,接下来我们证明这个算法的正确性:

引理1(贪心选择):若将S的元素从大到小排序,令x为排序后第一个使得\{x\} \in I的元素,那么必然存在一个包含x的最优子集。

证明:如果不存在x,则最优子集为空,显然。

否则,假设我们有一个不含x的最优子集B,显然由遗传性,对于y \in B都有\{y\} \in I,又因为我们选择x的方式显然由w(x) \ge w(y)。我们初始化A = \{x\},利用和B交换性不断拓展A直至|A| = |B|,此时必定存在另一元素y,使得A \setminus \{x\} = B \setminus \{y\},又因为w(x) \ge w(y),那么A一定不会比B差,得证。

引理2:若元素xA的一个拓展,那么\{x\} \in I,换而言之,x\emptyset的拓展。

证明:由定义,A \cup \{x\} \in I,由遗传性显然。

推论(逆否命题):x不是\emptyset的拓展,那它也一定不是其他非空独立子集的拓展。

引理3(最优子结构):在如上算法中选择完x之后,在M = (S, I)中寻找最优子集等价于在M'= (S', I')中寻找最优子集,其中:

\begin{aligned}
S' &= \{y \mid \{x, y\} \in S\} \\
I' &= \{B \mid B \subseteq S \setminus \{x\}, B \cup \{x\} \in I\}
\end{aligned}
我们可以忽略x继续我们的算法。

证明:如果我们在M'当中选出了最优子集A',则显然A' \cup \{x\}M的独立子集,并且由x的选择方式可知也是最优子集,证毕。

贪心正确性的证明:由引理2的推论,我们知道贪心算法没能一开始用来拓展的x一定在后面也没有用。由引理3,选择完x之后我们把问题缩小,还可以进一步贪心,此时贪心实质上是在M'上寻找最优子集。证毕。

从以上讨论我们可以看出,对于一类问题,如果我们可以以某种方式把它规约为在拟阵上求取最优子集,那你一定可以使用贪心解决,这给很多贪心算法(例如Kruskal)提供了理论支持。