Wannafly Camp 2020 Day 3C 无向图定向

https://ac.nowcoder.com/acm/contest/4114/C

dilworth定理,有向图可以理解成一个偏序集,偏序集上最小链划分中链的数量等于其反链长度的最大值。

最大链的长度等于最少反链覆盖数.而最大反链的长度等于最少链覆盖数

其中链的意思就是一个集合,且集合中两两可比,放在有向图中就是一条链,所以叫链

反链就是两两不可比的集合(其实叫对偶链好像形象一点

所以本题要让定向后的最大链最小,如果直接去枚举所有边的方向,再求最长路的长度,那么2^m*n是复杂度是不行的。

然而最大链的长度等于最少反链覆盖数,所以我们直接把他染色,相邻边不能颜色相同,用dfs去枚举所有点的情况,找出颜色数量最小的就行了,因为颜色的数量就是反链的数量,相同颜色之间不能两两比较,相邻边也就是可以直接比较的,所以不能再一个反链集合中。

至于为啥是最少颜色数-1,并不是很懂。。。不过看看样例应该可以吧

#include
using namespace std;
const int maxl=1010;

int n,m,ans;
int a[maxl];
bool g[maxl][maxl];

inline void dfs(int u,int tot)
{
	if(tot>=ans)
		return;
	if(u>n)
	{
		ans=min(u,tot);
		return ;
	} 
	bool flag;
	for(int i=1;i<=tot;i++)
	{
		flag=true;
		for(int v=1;v<=n;v++)
		if(a[v]==i && g[u][v])
			flag=false;
		if(!flag) continue;
		a[u]=i;
		dfs(u+1,tot);
		a[u]=0;
	}
	a[u]=tot+1;
	dfs(u+1,tot+1);
	a[u]=0;
}

int main()
{
	scanf("%d%d",&n,&m);
	int u,v;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&u,&v);
		g[u][v]=g[v][u]=true;
	}
	ans=n+1;
	dfs(1,0);
	printf("%d",ans-1);
	return 0;
}

 

你可能感兴趣的:(dilworth定理)