移动信号(树形Dp)

来源:互联网 发布:中级程序员报名 编辑:程序博客网 时间:2024/05/01 11:49

题目描述

给出一个树,有N个结点,结点编号从1至N。假如在第i个结点建立一个信号塔,那么与第i个结点有边相连的结点就能接受到信号,当然第i个结点本身也能接受到信号。
问题是:至少要在多少个结点建立信号塔,才能使得所有的结点都能接收到信息。

输入格式 1783.in

第一行,一个整数N。1 ≤ N ≤ 10,000
接下来有N-1行,每行两个整数:a b,表示结点a和结点b有边相连。1 ≤ A ≤ N; 1 ≤ B ≤ N; A ≠ B

输出格式 1783.out

一个整数。

输入样例 1783.in
5
1 3
5 2
4 3
3 5
输出样例 1783.out

2



这一题和普通的树形Dp有一点不一样。如果选了这一个点,不仅会影响到它的儿子,也会影响到它的父亲节点。则我们要设三个状态。为什么不是两个,选或者不选?其实,是把不选分成两种情况:f[i][0]表示这个节点依赖于它的儿子,而f[i][2]依赖于它的父亲,所以:f[i][1]表示自己选一个。

考虑三种状态的转移:

f[i][0]:它的儿子中起码有一个要选,而且都不能依赖于它们的父亲。则:f[i][0] = sum( min(f[son_i][0] , f[son_i][1] ))。

很可惜,这样的状态转移是错的。如果所有的min值都取f[son_i][0]呢?这样我们就需要记bo变量,看一看是否有min值不取f[son_i][0]的,若没有,为了维护最小值,就需要选f[son_i][1]与f[son_i][0]的差最小的儿子作为选择的节点。

f[i][1]:这样的话,它的所有的儿子如何选择都没有问题,则f[i][1] = sum( min(f[son_i][0] , f[son_i][1] , f[son_i][2]));

f[i][2]:则它的儿子不可以依赖于它的父亲,所以:f[i][2] = sum(min(f[son_i][0],f[son_i][1]));


有因为根节点没有父亲,所以f[root][2]不进行考虑,则答案为min(f[root][0],f[root][1])。

1 0