洛谷 P2016 战略游戏

题意简述简述

求一棵树的最小点覆盖

题解思路

树形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\n", std::min(dp[0][0], dp[0][1]));
}
posted @ 2018-10-23 20:27  xuyixuan  阅读(165)  评论(0编辑  收藏  举报