题意简述简述
求一棵树的最小点覆盖
题解思路
树形DP
dp[i][0]表示第i个点覆盖以i为根的子树的最小值,且第i个点不放士兵
dp[i][1]表示第i个点覆盖以i为根的子树的最小值,且第i个点放士兵
$ dp[i][0] = sum{dp[son[i]][1]} (
) dp[i][1] = sum{min(dp[son[i]][0], dp[son[i]][1])} $
代码
#include <cstdio>
#include <algorithm>
int n, x, y, k, cnt;
int h[2000], to[4000], nxt[4000];
int dp[2000][2];
inline void add_edge(const int& u, const int& v)
{
to[++cnt] = v;
nxt[cnt] = h[u];
h[u] = cnt;
}
void dfs(const int& x, const int& l)
{
dp[x][1] = 1;
dp[x][0] = 0;
for (register int i = h[x]; i; i = nxt[i])
if (to[i] != l)
{
dfs(to[i], x);
dp[x][1] += std::min(dp[to[i]][1], dp[to[i]][0]);
dp[x][0] += dp[to[i]][1];
}
}
int main()
{
scanf("%d", &n);
for (register int i = 1; i <= n; ++i)
{
scanf("%d%d", &x, &k);
for (register int i = 1; i <= k; ++i)
{
scanf("%d", &y);
add_edge(x, y);
add_edge(y, x);
}
}
dfs(0, -1);
printf("%d
", std::min(dp[0][0], dp[0][1]));
}