【最小路径可重点覆盖】Vani和Cl2捉迷藏

题意

给出一张有向无环图\(G=(V,E)\)\(|V|\leq 200,|E|\leq 30000\)
求出最多的\(k\)个点使得这\(k\)个点任意两个之间都没有路径相连。

思路

是一个点的集合,这个集合中任意两个元素\(u,v\),要么\(u\)能走到\(v\),要么\(v\)能走到\(u\)
反链是一个点的集合,这个集合中任意两点谁也不能走到谁
最长反链是反链中最长的那个。

该题即求最长反链。

Dilworth定理:最长反链长度=最小链覆盖数

故求出最小路径可重点覆盖即可。

代码

#include <cstdio>
#include <cstring>

const int V = 201, E = 30001;
int n, m, tot, ans;
int f[V][V];
int ver[E], next[E], head[V], line[V], v[V];

int find(int x) {
	for (int i = 1; i <= n; i++)
		if (f[x][i] && !v[i]) {
			v[i] = 1;
			if (!line[i] || find(line[i])) {
				line[i] = x;
				return 1;
			}
		}
	return 0;
}

int main() {
	scanf("%d %d", &n, &m);
	for (int i = 1, x, y; i <= m; i++)
		scanf("%d %d", &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++)
				f[i][j] |= f[i][k] && f[k][j];
	for (int i = 1; i <= n; i++) {
		memset(v, 0, sizeof(v));
		ans += find(i);
	}
	printf("%d", n - ans);
}
posted @ 2021-07-18 21:07  nymph181  阅读(39)  评论(0)    收藏  举报