ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【笔记】Dilworth定理

2022-05-16 20:33:40  阅读:168  来源: 互联网

标签:ch rp mat int 定理 笔记 fa Dilworth op


给定一个有向无环图,我们称 \(x,y\) 存在关系当且仅当存在 \(x\to y\) 或者 \(y \to x\) 的边。最长链为最大的集合使得其中任意两个元素存在关系,最长反链为最大的集合使得其中任意两个元素不存在关系。

Dilworth 定理:最长反链等于最小链覆盖。

最小链覆盖为用最少的链(可以相交)覆盖图的每一个点,我们传递闭包后即可转化为经典二分图模型:最小链划分。

如何求出具体方案?我们先求出链划分,然后先选取每条链的终点,只要存在两个点之间有关系,如 \(x\to y\),就将 \(y\) 沿着对应的链向起点走。可以证明重复这个过程可以得到答案。

听起来很复杂,但实现很简单。下面是 CF590E 的代码。

#define N 10000005
#define M 755
char s[N + M]; int idx, n, ch[N][2], fa[N], w[N], u[M], d[M][M], m, v[M], mat[M];
queue<int>q;
bool dfs(int x){
	rp(i, n)if(d[x][i] && !v[i]){
		v[i] = 1;
		if(!mat[i] || dfs(mat[i])){mat[i] = x; return true;}
	}return false;
}
vector<int>c;
int main() {
	read(n);
	rp(i, n){
		u[i] = ++m; scanf("%s", s + m);
		int l = strlen(s + m), x = 0;
		rp(j, l){
			int op = s[j + m - 1] - 'a';
			if(!ch[x][op])ch[x][op] = ++idx;
			x = ch[x][op];
		}
		w[x] = i, m += l;
	}
	if(ch[0][0])q.push(ch[0][0]);
	if(ch[0][1])q.push(ch[0][1]);
	while(!q.empty()){
		int x = q.front(); q.pop();
		if(!w[x])w[x] = w[fa[x]];
		if(ch[x][0])fa[ch[x][0]] = ch[fa[x]][0], q.push(ch[x][0]);
		else ch[x][0] = ch[fa[x]][0];
		if(ch[x][1])fa[ch[x][1]] = ch[fa[x]][1], q.push(ch[x][1]);
		else ch[x][1] = ch[fa[x]][1];
	}
	rp(i, n){
		int k = strlen(s + u[i]), x = 0;
		rp(j, k){
			if(w[x])d[i][w[x]] = 1;
			x = ch[x][s[j + u[i] - 1] - 'a'];
		}
		if(w[fa[x]])d[i][w[fa[x]]] = 1;
	}
	rp(k, n)rp(i, n)rp(j, n)d[i][j] |= d[i][k] & d[k][j];
	int ans = n;
	rp(i, n){
		memset(v, 0, sizeof(v));
		if(dfs(i))ans--;
	}
	printf("%d\n", ans);
	memset(v, 0, sizeof(v));
	rp(i, n)v[mat[i]] = 1;
	rp(i, n)if(!v[i])c.pb(i);
	while(true){
		memset(v, 0, sizeof(v));
		go(x, c)rp(i, n)if(d[x][i])v[i] = 1;
		int p = 0;
		for(auto &x : c)while(v[x])x = mat[x], p = 1;
		if(!p)break;
	}
	go(x, c)printf("%d ", x);el;
	return 0;
}

标签:ch,rp,mat,int,定理,笔记,fa,Dilworth,op
来源: https://www.cnblogs.com/7KByte/p/16278374.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有