偏序与Dilworth定理

[[TOC]]

前言

先从一个具体的问题开始:

一个导弹拦截系统打出的每一发炮弹都不能高于前一发。已知来袭导弹的高度序列为 a1,a2,,ana_1,a_2,\cdots,a_n,最少需要多少套系统才能拦截全部导弹?

一套系统能拦下的导弹高度形成一条不上升子序列,于是问题就变成:把整个序列切分成最少条不上升子序列,这个"最少切分数"是多少。

答案是:它等于序列的最长上升子序列的长度。

直觉上,"最少切分"和"最长某某"似乎是两个完全不相干的问题,但它们的答案居然相等。这个看似巧合的结论背后,是组合数学里一条漂亮的定理:Dilworth 定理。这一章我们先建立"偏序、链、反链"的概念,再证明这条定理,最后回到 OJ 上的应用。

偏序

定义 集合 PP 上的一个二元关系 \preceq 叫做偏序关系,如果对任意 x,y,zPx,y,z \in P:

  1. 自反性:xxx \preceq x
  2. 反对称性:若 xyx \preceq yyxy \preceq x,则 x=yx = y
  3. 传递性:若 xyx \preceq yyzy \preceq z,则 xzx \preceq z

(P,)(P,\preceq) 就叫做一个偏序集。我们记 xyx \prec y 表示 xyx \preceq yxyx \neq y

两个元素 x,yx,y 如果既没有 xyx \preceq y,也没有 yxy \preceq x,就称 xxyy 不可比

例子。

  1. 整除偏序:正整数集合上,xy    xyx \preceq y \iff x \mid y。例如 262 \preceq 6363 \preceq 6,但 2233 不可比。
  2. 排列偏序(本章最重要的例子):给定一个排列 a1,a2,,ana_1,a_2,\cdots,a_n,在元素 a1,a2,,ana_1,a_2,\cdots,a_n 上定义
aiaj    ij 且 aiaj a_i \preceq a_j \iff i \leqslant j \text{ 且 } a_i \leqslant a_j

按这个偏序,aia_iaja_j 不可比,当且仅当它们构成一个逆序对

链与反链

定义(P,)(P,\preceq) 是偏序集。

  • :集合 CPC \subseteq P,其中任意两个元素都可比。即 CC 中的元素可以从小到大排成一列。
  • 反链:集合 APA \subseteq P,其中任意两个元素都不可比

例如在排列偏序中,一条链就是一个递增子序列,一条反链就是一个递减子序列

链划分:把 PP 分成若干条互不相交的链,使得每个元素恰好属于一条链。

本章要回答的核心问题是:

把一个偏序集划分成链,最少需要多少条链?

一个具体情形:把序列切成最少的递增子序列

在进入一般定理之前,先完整解决排列上的特例。它本身就是一道 OJ 题(导弹拦截的第二问),而且解法可以直接写代码。

问题:给定排列 a1,a2,,ana_1,a_2,\cdots,a_n,把它切分成最少条递增子序列,求最少条数。

为什么这是 Dilworth 的特例。

在排列偏序下,一条链 = 一个递增子序列。所以"最少条递增子序列覆盖整个排列" = “最少链划分”。Dilworth 定理会说:这个答案等于最大反链的大小,也就是最长递减子序列的长度

最少递增子序列切分数=最长递减子序列长度 \text{最少递增子序列切分数} = \text{最长递减子序列长度}

下面我们先不引用 Dilworth,而是用一个贪心算法直接证明这个结论。

贪心:耐心排序

从前往后处理每个数 x=aix = a_i,把它放入某一"队"里。每一队必须保持递增,我们只关心每队的队尾(最后一个元素)。

贪心规则:

  • 若存在队尾小于 xx 的队,则把 xx 放入其中队尾最大的那一队;
  • 否则新开一队,队尾为 xx

例子。

序列 9 3 5 8 10 6:

处理的数 操作 各队
9 新开队 9
3 没有队尾 < 3,新开队 9,3
5 队尾 < 5 的有 3,放入 9,3 5
8 队尾 < 8 的有 5,放入 9,3 5 8
10 队尾 < 10 的有 9,放入 9 10,3 5 8
6 没有队尾 < 6,新开队 9 10,3 5 8,6

一共 3 队,而最长递减子序列为 9 8 6,长度也是 3。

贪心的证明

设贪心最终开了 mm 队,最长递减子序列的长度为 LDSLDS

方向一:mLDSm \leqslant LDS

贪心有一个不变量:各队的队尾从左到右严格递减

  • 新开一队时,新队尾 xx 小于所有队尾(否则就存在队尾 <x< x 的队了),放在最右边,递减性保持。
  • 放入某队时,设 xx 放入第 kk 队,则第 k1k-1 队的队尾 x\geqslant x(否则队尾更大的队 k1k-1 也满足条件,xx 不会放第 kk 队),且 x>x >kk 队旧队尾,所以替换队尾后递减性保持。

现在建立指针链:每个元素 xx 放入第 kk 队时(k2k \geqslant 2),记录它入队那一刻第 k1k-1 队的队尾 yy。由上面知道 yxy \geqslant x(排列中元素两两不同,即 y>xy > x),并且 yy 是"过去"的元素,在时间上早于 xx

从最后一队的队尾出发,沿着指针链往回走:每走一步,值严格变小、时间严格变早。于是得到一条长度恰好为 mm递减子序列。所以 LDSmLDS \geqslant m,即 mLDSm \leqslant LDS

方向二:mLDSm \geqslant LDS

取一条最长递减子序列 d1>d2>>dLDSd_1 > d_2 > \cdots > d_{LDS}。其中任意两个元素 di,djd_i,d_j(i<ji<j)都构成逆序对,所以不可能出现在同一个递增子序列里,也就是不可能同一队。

于是一条递减子序列里的 LDSLDS 个元素分布在至少 LDSLDS 个不同的队中。任何切分方案(包括贪心)的队数都 LDS\geqslant LDS,所以 mLDSm \geqslant LDS

两个方向合起来:

m=LDS m = LDS

也就是说,贪心开出的队数就是答案,而且最少递增子序列切分数 = 最长递减子序列长度

代码实现

用二分维护队尾数组。队尾严格递减,插入时在队尾数组里找第一个队尾 <x< x 的位置,没有就新开一队:

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

// 把排列切成最少条递增子序列,答案 = 最长递减子序列长度
int main(){
    int n;
    scanf("%d",&n);
    vector<int> tails; // 各队的队尾,严格递减
    for(int i=1;i<=n;i++){
        int x;
        scanf("%d",&x);
        // 找第一个队尾 < x 的队(递减数组上用 greater 的 upper_bound)
        auto it = upper_bound(tails.begin(), tails.end(), x, greater<int>());
        if(it == tails.end())      // 没有队尾 < x 的队,新开一队
            tails.push_back(x);
        else
            *it = x;               // 放入该队,更新队尾
    }
    printf("%d\n", (int)tails.size());
    return 0;
}

时间复杂度 O(nlogn)O(n \log n)

Dilworth 定理

序列上的特例证明完了。现在把结论推广到任意有限偏序集

定理(Dilworth)(P,)(P,\preceq) 是有限偏序集,则

把 P 划分成链的最少条数= P 中最大反链的大小 \text{把 } P \text{ 划分成链的最少条数} = \text{ } P \text{ 中最大反链的大小}

特例与它完全一致:链 = 递增子序列,反链 = 递减子序列。

关于下界。

一半是显然的:每条链最多包含反链中的一个元素,所以任何链划分的条数都 \geqslant 任何反链的大小,因此"最少链数 \geqslant 最大反链大小"。难的永远是另一个方向:证明 ww 条链足够

需要的图论工具

Dilworth 的证明要借助二分图里的两条引理。我们先定义相关概念。

二分图:顶点分成左右两部分 XXYY,每条边连接一个 XX 顶点和一个 YY 顶点。

  • 匹配:一组两两没有公共端点的边。匹配的大小 = 边的条数,记最大匹配为 ν\nu
  • 顶点覆盖:一个顶点集合,使得每条边至少有一个端点在这个集合里。最小顶点覆盖的大小记为 τ\tau
  • 交替路:依次经过"非匹配边、匹配边、非匹配边、匹配边、……"的路。
  • 增广路:两端都是未匹配点的交替路。

引理 1(增广路)MM 是一个匹配。若存在一条关于 MM 的增广路,则把这条路上每条边的"是否属于 MM"全部翻转,得到的新匹配大小是 M+1|M| + 1

证明:增广路的两个端点原来都未匹配,翻转后它们被匹配;路径内部每个点原来有恰好一条匹配边与之相连,翻转后仍然恰好一条。整条路上非匹配边比匹配边恰好多 11 条(第一条和最后一条都是非匹配边),所以匹配大小增加 11

因此:最大匹配一定没有增广路,否则还能变大。

引理 2(König 定理) 在二分图里,最大匹配的大小 = 最小顶点覆盖的大小,即 ν=τ\nu = \tau

证明:任何顶点覆盖的大小都 \geqslant 任何匹配的大小,因为匹配的每条边至少要占用一个不同的覆盖顶点,所以 τν\tau \geqslant \nu

下面证明 τν\tau \leqslant \nu。设 MM 是最大匹配。令 X0X_0XX 中所有未匹配的点,从 X0X_0 出发走交替路,能到达的 XX 侧顶点集合记为 SS(显然 X0SX_0 \subseteq S),能到达的 YY 侧顶点集合记为 TT

先观察三个性质:

  1. TT 中的点都被匹配,而且匹配对象在 SS:设 tTt \in T,交替路最后一条边是 SSTT 的非匹配边。若 tt 未匹配,这条交替路就是增广路,矛盾。所以 tt 被匹配;交替路可以沿这条匹配边继续走到 tt 的匹配对象 xx,故 xSx \in S
  2. 不存在从 SSYTY \setminus T 的边:设 sSs \in S,边 (s,y)(s,y)。若它是非匹配边,交替路延伸到 yy,于是 yTy \in T,矛盾;若它是匹配边,则到达 ss 的交替路的最后一条边就是 (y,s)(y,s),于是 yTy \in T,也矛盾。
  3. XSX \setminus S 中的点都被匹配:未匹配的点都在 X0SX_0 \subseteq S 里。

于是 C=(XS)TC = (X \setminus S) \cup T 是一个顶点覆盖:与 XSX \setminus S 相连的边被 XSX \setminus S 覆盖,其余边由性质 2 知都连着 TT

最后算 CC 的大小:由性质 1,TTSX0S \setminus X_0 通过匹配边一一对应,所以 S=T+X0|S| = |T| + |X_0|。而每条匹配边恰好对应一个被匹配的 XX 顶点,M=XX0|M| = |X| - |X_0|。于是

C=XS+T=XS+T=XX0=M |C| = |X \setminus S| + |T| = |X| - |S| + |T| = |X| - |X_0| = |M|

τM=ν\tau \leqslant |M| = \nu。结合 τν\tau \geqslant \nuτ=ν\tau = \nu

Dilworth 定理的证明

n=Pn = |P|。构造一个二分图 GG:

  • 左部是 PP 的一份拷贝:P={xxP}P^- = \{ x^- \mid x \in P \};
  • 右部是 PP 的另一份拷贝:P+={x+xP}P^+ = \{ x^+ \mid x \in P \};
  • 连边 xy+    xyx^- y^+ \iff x \prec y

关键对应一:匹配与链划分。

大小为 mm 的匹配     \iffPP 划分成 nmn - m 条链。

  • (    )( \implies ) 初始把每个元素看作一条单点链,共 nn 条。对匹配中每条边 (x,y+)(x^-,y^+),把 yy 接到 xx 的正上方(因为 xyx \prec y,连接合法)。匹配的左端点两两不同、右端点两两不同,所以每个元素"接到它正上方的人"和"它接的人"都至多一个;且沿着拼接方向元素严格变大,不可能绕出环。每连一条边,链数减一,最终 nmn - m 条链。
  • (    )( \impliedby )PP 划分成 cc 条链,取每条链里所有相邻元素对,一共 ncn - c 对。不同链的元素对端点互不相交,且每对都满足 xyx \prec y,所以它们构成大小为 ncn - c 的匹配。

于是:

最少链划分条数=nν \text{最少链划分条数} = n - \nu

关键对应二:顶点覆盖与反链。

CCGG 的一个顶点覆盖,C=s|C| = s。令

I={xPxC 且 x+C} I = \{ x \in P \mid x^- \notin C \text{ 且 } x^+ \notin C \}

即两份拷贝都未被覆盖的那些元素。

  • Ins|I| \geqslant n - s:被覆盖的 nIn - |I| 个元素每个至少贡献一个被覆盖的拷贝。
  • II 是反链:若 x,yIx,y \in Ixyx \prec y,则边 (x,y+)(x^-, y^+) 的两个端点都未被覆盖,矛盾。

所以 PP 中存在大小至少为 nsn - s 的反链。取 CC 为最小顶点覆盖,得

最大反链大小  wnτ \text{最大反链大小} \; w \geqslant n - \tau

合龙:由 König 定理 ν=τ\nu = \tau,于是

最少链划分条数=nν=nτw最少链划分条数 \text{最少链划分条数} = n - \nu = n - \tau \leqslant w \leqslant \text{最少链划分条数}

最后一个不等式就是一开始的下界。因此两者相等,Dilworth 定理得证。

证明小结。

Dilworth 定理其实等价于二分图里的 König 定理:把偏序的每个元素复制成左右两份,匹配对应"把链拼起来",顶点覆盖对应"剩下的元素构成反链"。

Mirsky 定理(对偶)

把"链"与"反链"的角色互换,还有一条对偶的定理:

定理(Mirsky)PP 划分成反链的最少条数 = PP 中最长链的大小。

这条定理的证明很简单:定义 h(x)h(x) 为"以 xx 结尾的最长链的长度",把所有 hh 值相同的元素放在一起。

  • 每一层都是反链:若同一层里 xyx \prec y,则 h(y)h(x)+1h(y) \geqslant h(x) + 1,矛盾。
  • 层数恰好等于最长链的大小 hmaxh_{\max}

所以 hmaxh_{\max} 层反链覆盖了 PP;而每条链最多包含每条反链中的一个元素,任何反链划分的条数都 hmax\geqslant h_{\max}。得证。

注意方向。

导弹拦截的第二问用的是 Dilworth(链 = 非上升子序列,反链 = 上升子序列,最少链数 = 最大反链),而不是 Mirsky。两个定理方向相反,不要混用。

应用

导弹拦截

拦截系统打出的高度序列是一条不上升子序列。定义偏序

aiaj    ij 且 aiaj a_i \preceq a_j \iff i \leqslant j \text{ 且 } a_i \geqslant a_j

则链 = 不上升子序列,反链 = 严格上升子序列。由 Dilworth:

最少系统数=最长严格上升子序列长度 \text{最少系统数} = \text{最长严格上升子序列长度}

第一问"一套系统最多拦多少"就是最长不上升子序列,一个 O(nlognn \log n) 模板同时解决两问。

逆序图染色

有一个从排列构造的图:当 i<ji < jai>aja_i > a_j 时,节点 iijj 之间有一条边。求给这个图染色,使相邻点颜色不同,最少需要多少种颜色。

  • 同色的点之间不能有边,也就是同色的点两两不构成逆序对,按下标排开后值严格递增:每种颜色恰好对应一个递增子序列
  • 于是最少颜色数 = 把排列切成最少条递增子序列的条数 = 最长递减子序列长度。

这正是一开始特例的结论。n 可以到 10610^6,用上面的 O(nlogn)O(n \log n) 贪心即可。

练习题目

参考