题目描述
给出一张有向无环图,选出K个点,使得这K个点相互不连通,现在求最大的K
样例输入
4 4
1 2
3 2
3 4
4 2
样例输出
2
思路
这道题就是求一个最长反链长度,根据Dilworth定理,可以得知最小链覆盖就是这个最长反链长度 证明->this
然后这个最小链覆盖在不能相交的情况下
ta就等于点数n - 最大匹配数
但是我们这张图它是有相交情况的,所以我们要用floyd来传递闭包(相当于是一个点可以到达的点都直接连边)
最大匹配可以用匈牙利算法(或是网络流)
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int t, n, m, sum, x, y;
int f[5005][5005];
int h[5005], link[5005], vis[5005];
struct node
{
int to, next;
}g[5000005];
void add(int x, int y)
{
g[++t] = (node){y, h[x]}; h[x] = t;
}
bool find(int x)
{
for(int i = h[x]; i; i = g[i].next)
{
int to = g[i].to;
if(!vis[to]) {
vis[to] = 1;
int p = link[to];
link[to] = x;
if(p == 0 || find(p)) return 1;
link[to] = p;
}
}
return 0;
}//求最大匹配(匈牙利算法)
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; ++i)
{
scanf("%d%d", &x, &y);
add(x, y), f[x][y] = 1;
}
for(int k = 1; k <= n; ++k)
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
{
if(i != j && j != k && k != i)
{
if(f[i][k] && f[k][j])
f[i][j] = 1,
add(i, j);
}
}//floyd传递闭包
for(int i = 1; i <= n; ++i)
{
memset(vis, 0, sizeof(vis));
if(find(i)) sum++;
}
printf("%d", n - sum);
return 0;
}