https://ac.nowcoder.com/acm/contest/4114/C
dilworth定理,有向图可以理解成一个偏序集,偏序集上最小链划分中链的数量等于其反链长度的最大值。
最大链的长度等于最少反链覆盖数.而最大反链的长度等于最少链覆盖数
其中链的意思就是一个集合,且集合中两两可比,放在有向图中就是一条链,所以叫链
反链就是两两不可比的集合(其实叫对偶链好像形象一点
所以本题要让定向后的最大链最小,如果直接去枚举所有边的方向,再求最长路的长度,那么2^m*n是复杂度是不行的。
然而最大链的长度等于最少反链覆盖数,所以我们直接把他染色,相邻边不能颜色相同,用dfs去枚举所有点的情况,找出颜色数量最小的就行了,因为颜色的数量就是反链的数量,相同颜色之间不能两两比较,相邻边也就是可以直接比较的,所以不能再一个反链集合中。
至于为啥是最少颜色数-1,并不是很懂。。。不过看看样例应该可以吧
#include<bits/stdc++.h>
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;
}