题意
题解
求解 D A G DAG DAG 的最小路径点覆盖,即使用尽量少的不相交的路径,覆盖 D A G DAG DAG 的所有节点。将 D A G DAG DAG 各点拆为两个点,分别为二分图的左部点与右部点,对原图的每条有向边,从起点的左部点向终点的右部点连边。此时左部匹配点可以看做一段路径上的起点,左部非匹配点可以看做一段路径上的终点。目标是最小化终点数,那么答案为原图节点数减去二分图的最大匹配。
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 125;
int T, N, M, match[maxn];
bool G[maxn][maxn], vs[maxn];
bool dfs(int x)
{
for (int y = 1; y <= N; ++y)
if (G[x][y] && !vs[y])
{
vs[y] = 1;
int w = match[y];
if (!w || dfs(w))
{
match[y] = x;
return 1;
}
}
return 0;
}
int main()
{
scanf("%d", &T);
while (T--)
{
memset(G, 0, sizeof(G));
scanf("%d%d", &N, &M);
for (int i = 1, x, y; i <= M; ++i)
scanf("%d%d", &x, &y), G[x][y] = 1;
int res = N;
memset(match, 0, sizeof(match));
for (int i = 1; i <= N; ++i)
memset(vs, 0, sizeof(vs)), res -= dfs(i);
printf("%d\n", res);
}
return 0;
}