【最小路徑可重點覆蓋】Vani和Cl2捉迷藏
阿新 • • 發佈:2021-07-18
題意
給出一張有向無環圖\(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); }