Dilworth定理是个啥东东

本文深入解析Dilworth定理,阐述其在偏序集、全序集及反链概念中的核心作用,并通过洛谷P1020导弹拦截与P4298/bzoj1143祭祀等例题,详细展示如何运用该定理解决实际问题,包括最长反链长度的计算与最少路径覆盖的求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Dilworth定理

Dilworth定理,一言以蔽之,偏序集能划分成的最少的全序集个数等于最大反链的元素个数

这对于数学不好的人(如litble)来说,不是句人话。翻译一下几个概念:

偏序

偏序嘛,应该不是那么陌生的东西 ,所谓“时属九月,三维偏序”

定义集合AAA中的一个二元关系≤\leq,譬如对于(a1,b1)(a_1,b_1)(a1,b1)(a2,b2)(a_2,b_2)(a2,b2)两个元素,我可以定义(a1,b1)≤(a2,b2)(a_1,b_1) \leq (a_2,b_2)(a1,b1)(a2,b2)当且仅当a1≤a2a_1 \leq a_2a1a2b1≤b2b_1 \leq b_2b1b2,而若a1>a2a_1>a_2a1>a2b1≤b2b_1 \leq b_2b1b2,这两个元素就不可比了。

在满足以下三个条件时,(A,≤)(A,\leq)(A,)就是个偏序集:

1.自反性:∀a∈A,a≤a\forall a \in A,a \leq aaA,aa

2.反对称性:∀a,b∈A\forall a,b \in Aa,bA,若a≤b,b≤aa \leq b,b \leq aab,ba,则a=ba=ba=b

3.传递性:∀a,b,c∈A\forall a,b,c \in Aa,b,cA,若a≤b,b≤ca \leq b, b \leq cab,bc,则a≤ca \leq cac

全序集

≤\leq为非空集合AAA上的一个偏序关系,若对于集合∀a,b∈B\forall a,b \in Ba,bB,都有a≤ba \leq babb≤ab \leq aba(即元素两两可比),就称(B,≤)(B, \leq)(B,)为一个全序集。

反链

若偏序集(B,≤)(B, \leq)(B,)中的元素两两不可比,则称BBB为反链。

例题

洛谷P1020 导弹拦截

我们若设每一个元素为二元组(a,b)(a,b)(a,b)aaa是这颗导弹的抵达时间,bbb是高度,那么令偏序关系≤\leq为:a1≤a2a_1 \leq a_2a1a2b1≥b2b_1 \geq b_2b1b2

第二问问的是最少被划分为多少全序集,也就是要求最长反链长度,也就是求两两满足满足a1≤a2a_1 \leq a_2a1a2b1&lt;b2b_1 &lt; b_2b1<b2的最大集合,也就是求最长严格下降子序列长度。

洛谷P4298/bzoj1143 祭祀

令偏序关系≤\leqaaa能到达bbb,题问要求的是最长反链长度,就求最少被划分为多少全序集,也就是求最少路径覆盖。

至于输出方案呢,第一问是从每一个左侧未匹配点出发遍历匈牙利树,将沿途的所有点打上标记。如果一个原图中的点,在左边的分点打了标记,在右边的没打,就是一个祭祀点。至于为什么,litble太蠢暂未搞懂,希望大神在评论中指教,感激不尽。

第二问是枚举所有点,删除和它可比(可达它或它可达)的所有点,跑一遍最少路径覆盖,若只比原答案少1,则这个点可以作为祭祀点。

#include<bits/stdc++.h>
using namespace std;
#define RI register int
const int N=105;
int n,m,tot,ans,tim;
int h[N],ne[N*N],to[N*N],L[N][N],havcp[N],cp[N],vis[N];
int bj1[N],bj2[N],ban[N];

void floyed() {
	for(RI k=1;k<=n;++k)
		for(RI i=1;i<=n;++i)
			for(RI j=1;j<=n;++j)
				if(i!=k&&k!=j&&i!=j&&L[i][k]&&L[k][j]) L[i][j]=1;
}
void add(int x,int y) {to[++tot]=y,ne[tot]=h[x],h[x]=tot;}
int dfs(int x) {
	bj1[x]=1;
	for(RI i=h[x];i;i=ne[i])
		if(vis[to[i]]!=tim&&!ban[to[i]]) {
			vis[to[i]]=tim,bj2[to[i]]=1;
			if(!cp[to[i]]||dfs(cp[to[i]]))
				{havcp[x]=1,cp[to[i]]=x;return 1;}
		}
	return 0;
}

void print() {
	for(RI i=1;i<=n;++i) bj1[i]=bj2[i]=0;
	for(RI i=1;i<=n;++i) if(!havcp[i]) ++tim,dfs(i);
	for(RI i=1;i<=n;++i) printf("%d",bj1[i]&&!bj2[i]);
	puts("");
	for(RI i=1;i<=n;++i) {
		for(RI j=1;j<=n;++j) cp[j]=ban[j]=0;
		int js=0;
		for(RI j=1;j<=n;++j)
			if(L[j][i]||L[i][j]||i==j) ban[j]=1;
			else ++js;
		for(RI j=1;j<=n;++j) {
			if(ban[j]) continue;
			++tim;if(dfs(j)) --js;
		}
		printf("%d",js==ans-1);
	}
}
int main()
{
	int x,y;
	scanf("%d%d",&n,&m);
	for(RI i=1;i<=m;++i) scanf("%d%d",&x,&y),L[x][y]=1;
	floyed();
	for(RI i=1;i<=n;++i)
		for(RI j=1;j<=n;++j)
			if(i!=j&&L[i][j]) add(i,j);
	ans=n;
	for(RI i=1;i<=n;++i) {++tim;if(dfs(i)) --ans;}
	printf("%d\n",ans);
	print();
	return 0;
}
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值