【总结】图论基础知识(DAG&特殊的二分图&Dilworth定理)bzoj1143祭祀river

博客探讨了DAG(有向无环图)和二分图中的Dilworth定理,详细解释了偏序集、链、反链等概念,并阐述了最长反链与最小链覆盖的关系。通过最大匹配和最小点覆盖的转换,解决了如何找到最长反链的问题。此外,还讨论了如何判断图中点是否可能出现在最长反链中,并给出了相关构造方法和代码实现。

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

传送门:bzoj1143


题解

r_64的uoj博客中看到这题原本有三个问题:

1)最长反链的长度;

2)一个最长反链;

3)哪些元素可能在最长反链中。

第一问(也就是题目中的问题)即求图的最长反链。

下面先介绍一些关于 D A G DAG DAG的概念,以及之间的关系。

二分图?简单来说就是没有奇环的图。


Dilworth定理

偏序集

P P P为集合, P P P上的二元关系 ≤ \leq 满足:

  • 自反性: x ≤ x x\leq x xx
  • 反对称性: a ≤ b , b ≤ a → a = b a\leq b,b\leq a\to a=b ab,baa=b
  • 传递性: a ≤ b , b ≤ c → a ≤ c a\leq b,b\leq c\to a\leq c ab,bcac

则称 ≤ \leq P P P上的偏序关系。具有偏序关系的集合 P P P称为偏序集,记为 ( P , ≤ ) (P,\leq) (P,)
a ≤ b a\leq b ab b ≤ a b\leq a ba,则称 a , b a,b a,b是可比的,否则就称 a , b a,b a,b是不可比的,记作 a ∣ ∣ b a||b ab
-----摘自百度百科

链: P P P的子集,满足集合中任意两不同元素可比。
反链: P P P的子集,满足集合中任意两不同元素不可比。
(这里的链不仅指图上的链,是更广泛的数学概念)

对偶定理
  • P P P的链划分最少集合,等于其最长反链长度。
  • P P P的反链划分最少集合,等于其最长链长度。

最长反链=最小链覆盖

这个结论显然就可以由上面的对偶定理得到了。
D A G DAG DAG中的偏序关系定义为:若点 a a a可以通过图上有向边到达点 b b b或点 b b b可到达点 a a a a , b a,b a,b即是可比的,否则不可比。
最长反链的点集中任意两点不可比。
最小链覆盖就是将 D A G DAG DAG划分成链的最少链数。


DAG的各种概念与二分图上的结论

概念
  1. 最大匹配: D A G DAG DAG中边集 E E E中任意两条边没有公共顶点。
  2. 最小点覆盖: D A G DAG DAG中最小的点集 S S S满足 D A G DAG DAG中每条边至少有一个顶点 ∈ S \in S S
  3. 最大点独立集: D A G DAG DAG中最大的点集 S S S满足点集中任意不同的两个顶点不共用一条边。
  4. 最大团: D A G DAG DAG中的最大点集 S S S满足集合中任意不同的两个顶点之间有连边。
结论

这些概念搬到二分图上后,产生了一些特殊的性质。

  1. 二分图最小点覆盖=二分图最大匹配数
  2. D A G DAG DAG最小链覆盖数= D A G DAG DAG节点数-对应二分图最大匹配数
  3. 最大点独立集= D A G DAG DAG节点数-对应二分图
  4. 二分图的最大团=补图的最大点独立集
具体证明及构造方法

详见推荐博文:二分图的最小顶点覆盖 最大独立集 最大团-将狼踩尽 19891101

有了这些结论,就可以轻松解决第一问了。


构造最长反链

设二分图中 x ( a ) , y ( a ) x(a),y(a) x(a),y(a)分别表示顶点 a a a X , Y X,Y X,Y部中的点。
在构造二分图求出最大点独立集 I I I后,若 x ( a ) ∈ I , y ( a ) ∈ I x(a)\in I,y(a)\in I x(a)I,y(a)I,则 a a a在最长反链上。而r-64的题解中也证明了这样构造出的反链是最长的。


判断点出现可能

至于最后一个问题,只需要枚举每个点,在将与当前点可比的点(包括该点本身)全部删去后的二分图跑最大匹配,若恰比答案少1,则该点能够出现在最长反链上。


代码

#include<bits/stdc++.h>
#define RI register
using namespace std;

const int N=105;

int n,m,num,ans,bel[N],in[N];
int g[2][N][N],nw,used[N],res[N];

inline bool dfs(int x)
{
	RI int i;
	for(i=1;i<=num;++i)
	 if(!used[i] && g[nw][x][i]){
	    used[i]=1;
		if(!bel[i] || dfs(bel[i])){
			bel[i]=x;return true;
		}	
	 }
	return false;
}

inline int maxmatch()
{
	RI int i,re=0;
	memset(bel,0,sizeof(int)*(n+3));
	for(i=1;i<=num;++i){
		memset(used,0,sizeof(int)*(num+3));
		if(dfs(i)) re++;
	}
	return re;
}

inline int del(int x)
{
	RI int i,j;num=0;
	for(i=1;i<=n;++i)
	 if(i!=x && (!g[0][x][i]) && (!g[0][i][x]))
	  res[++num]=i;
	for(i=1;i<=num;++i)
	 for(j=1;j<=num;++j)
	  g[1][i][j]=g[0][res[i]][res[j]];
	return num-maxmatch();
}

int main(){
	RI int i,j,k,x,y;
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;++i){
		scanf("%d%d",&x,&y);
		g[0][x][y]=1;
	}
    for(k=1;k<=n;++k)
	 for(i=1;i<=n;++i)
	  for(j=1;j<=n;++j)
	   g[0][i][j]|=(g[0][i][k]&g[0][k][j]);
    nw=0;num=n;
	ans=n-maxmatch();
	printf("%d\n",ans);
	for(i=1;i<=n;++i) if(bel[i]) in[bel[i]]=1;
	memset(used,0,sizeof(int)*(n+3));
	for(i=1;i<=n;++i) if(!in[i]) dfs(i);
	for(i=1;i<=n;++i) in[i]^=1;
	for(i=1;i<=n;++i) in[bel[i]]=used[i];
	for(i=1;i<=n;++i){
	  if(in[i] && (!used[i]))
	    putchar('1');
	  else putchar('0');
	}
	puts("");nw=1;
	for(i=1;i<=n;++i) putchar('0'+(del(i)==ans-1));
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值