【问题描述】
Bob喜欢玩电脑游戏,特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。他要建立一个古城堡,城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能了望到所有的路。注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被了望到。请你编一程序,给定一树,帮Bob计算出他需要放置最少的士兵.
【输入格式】
测试数据表示一棵树,描述如下:
第一行 N,表示树中结点的数目。
第二行至第N+1行,每行描述每个结点信息,依次为:该结点标号i,k(后面有k条边与结点I相连)。接下来k个数,分别是每条边的另一个结点标号r1,r2,...,rk。
对于一个n(0 【输出格式】 输出文件仅包含一个数,为所求的最少的士兵数目。 例如,对于如下图所示的树: 0 | 1 / \ 2 3 答案为1(只要一个士兵在结点1上)。 【输入样例1】 4 0 1 1 1 2 2 3 2 0 3 0 1 【输入样例2】 5 3 3 1 4 2 1 1 0 2 0 0 0 4 0 【输出样例2】 2 【解析】 这道题和上一道【皇宫看守(guard)】有相似之处..但是这道题的状态定义与上一题有少许不同.. 上一道题需要点安全,但这一道题是需要边安全 = = 这是个值得困扰的问题.. 你要边安全但是又只能搜索点0.0 那么我们就可以这样定义每一个点所代表的 比如说点i,我们就可以说点i是否有人,点i所连接的边(以i为根的树,同下)是否安全。这样来做一个状态,我们又可以像上一题那样分出4种状态。 f[i][0] 表示点i 没人 所连接的边 安全 的最小花费 f[i][1] 表示点i 没人 所连接的边 不安全 的最小花费 f[i][2] 表示点i 有人 所连接的边 安全 的最小花费 f[i][3] 表示点i 有人 所连接的边 不安全 的最小花费 #既然有人怎么会不安全呢.. 所以这种状态可以不管0.0 这个时候问题也就来了.. 没人不安全这个状态有没有用呢.. 上一题是看点是否安全的,也就是说,以下这种状态是成立的(1表示有人,0表示没人): 1——0——0——1(根) 这样子四个点都是安全的。 但现在需要的是边安全,那么在同样情况下: 1——0——0——1(根) 这是不安全的,因为红色的边这一条边是不安全的,而蓝色这一个点的状态正是 没人不安全.. 以上证明:没人不安全 这个状态是没有用的! 那么同样的道理,没人安全这种状态就需要孩子节点全都是有人安全的! 那这道题就轻易解决啦! 【核心代码】
【完整代码】
void Tree_DP ( int x ){
int i, j, k, f0, f1;
f0 = 0; f1 = 1;
for ( k = first[x]; k; k = a[k].next ){
int y = a[k].y;
Tree_DP (y);
f0 += f[y][1];
f1 += _min ( f[y][1], f[y][0] );
}
f[x][0] = f0;
f[x][1] = f1;
}
#include