树形DP初步-真树1662

树形DP初步-真树

时间限制: 1000 ms 内存限制: 65536 kb

总通过人数: 119 总提交人数: 123

题目描述

新年到了,白兔家族要搞大大的聚会。但是并不是每只白兔都是同一辈分的,于是便有一棵以老白兔为根的家族树。

每只白兔都有它们自己唯一的整数编号(范围在1到N之间),并且对应一个参加聚会所得的开心值。为了使每个参加聚会的白兔都巨开心,老白兔想让每只白兔和他的上一代白兔不会同时参加聚会。

求参加聚会的白兔获得的最大总开心值。

输入

输入的第一行是一个整数N,1<= N <= 6000

以下的N行是对应的N个白兔的开心值(开心值是一个从-128到127之间的整数)

接着是白兔的家族树,树的每一行格式如下: 每行输入一对整数L,K。表示第K个白兔是第L个白兔的上一代。 输入以0 0表示结束

输出

参加聚会的白兔获得的最大总开心值

输入样例

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0

输出样例

5

AC代码
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #define maxn 6007
 5 using namespace std;
 6
 7 int n;
 8 int dp[maxn][2],father[maxn];
 9
10
11 void tree_dp(int node)
12 {
13     int i;
14
15     for(int i=1;i<=n;i++)             //对树遍历。树的深度游戏先搜索
16     {
17         if(father[i]==node)
18         {
19             tree_dp(i);
20             dp[node][1]+=dp[i][0];
21             dp[node][0]+=max(dp[i][0],dp[i][1]);
22         }
23     }
24 }
25
26 int main()
27 {
28     int a,b;
29     int root=0;
30     scanf("%d",&n);
31     for(int i=1;i<=n;i++)
32     {
33         scanf("%d",&dp[i][1]);
34     }
35     scanf("%d%d",&a,&b);
36     while(!(a==0&&b==0))
37     {
38         father[a]=b;
39
40         scanf("%d%d",&a,&b);
41     }
42     root=b;
43     //找到根节点
44     while(father[root])
45     {
46         root=father[root];
47     }
48     //从根节点开始dp
49     tree_dp(root);
50     printf("%d\n",max(dp[root][0],dp[root][1]));
51 }

1.求相邻节点不同时取的最大节点权值和。
2.考虑序列中相邻不同取的dp:f[i][0]表示前i个,i不取的最优值;f[i][1]表示前i个,i取的最值;
同理到树形dp:f[i][0]表示i为根的子树中,i不取的最优值;f[i][1]同理。
3.则在dfs过程中,顺道dp;
4.f[i][0] = ∑max(f[j][1], f[j][0]),j为i的儿子;
f[i][1] = a[i] + ∑f[j][0],j为i的儿子,a[i]为i自身的价值。
5.答案为max(f[root][0], f[root][1])

6.注:此题由于树的结构的特殊性,自顶向下生成时并不会产生子问题的重复计算(每棵子树只对它的父节点产生贡献,这棵子树的信息只被用到一次)



原文地址:https://www.cnblogs.com/loganlzj/p/10093470.html

时间: 2024-10-20 01:08:29

树形DP初步-真树1662的相关文章

NOIP2011pj表达式的值[树形DP 笛卡尔树]

题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例如:计算表达式A⊕B × C时,先计算 B × C,其结果再与 A 做⊕运算. 现给定一个未完成的表达式,例如+(*_),请你在横线处填入数字0 或者1 ,请问有多少种填法可以使得表达式的值为0 . 输入输出格式 输入格式: 输入文件名为exp.in ,共 2 行. 第1 行为一个整数 L,表示给定的表达式中除去横线外的运

poj 1655 树形dp求取树的重心

http://poj.org/problem?id=1655 Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or more trees. Define the balance of a node to be the size of the large

HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形dp, 对于每条链u,v,w,我们只在lca(u,v)的顶点上处理它 让dp[i]表示以i为根的指数的最大值,sum[i]表示dp[vi]的和(vi为i的儿子们) 则i点有两种决策,一种是不选以i为lca的链,则dp[i]=sum[i]. 另一种是选一条以i为lca的链,那么有转移方程:dp[i]=

POJ 3123 Ticket to Ride 状压dp+树形dp 斯坦纳树

题目链接:点击打开链接 题意: 给定n个城市和m条可选择修建的道路 下面n行给出每个城市的名字 下面m行给出每条道路及修建该道路的花费. 下面4行,每行给出一对城市. 目标:使得最后4行的每对城市连通(不同对之间可以不连通)所需要修建的最小花费. 数据保证存在可行解 思路: 首先如果这个问题问的是所有城市都连通,就是一个最小生成树的问题. 这里就相当于多个最小生成树的 问题. 当然图里我们只关心最后的4行8个点,所以我们状压这8个点. 设dp[i][j] 表示以i为根 ,j为8个点中是否在 i

树形DP+(分组背包||二叉树,一般树,森林之间的转换)codevs 1378 选课

codevs 1378 选课 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修了这M门课并考核通过就能获得相应的学分. 在选修课程中,有些课程可以直接选修,有些课程需要一定的基础知识,必须在选了其它的一些课程的基础上才能选修.例如<Frontpage>必须在

hdu5293 Tree chain problem 树形dp+线段树

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5293 在一棵树中,给出若干条链和链的权值.求选取不相交的链使得权值和最大. 比赛的时候以为是树链剖分就果断没去想,事实上是没思路. 看了题解,原来是树形dp.话说多校第一场树形dp还真多. . .. 维护d[i],表示以i为根节点的子树的最优答案. sum[i]表示i的儿子节点(仅仅能是儿子节点)的d值和. 那么答案就是d[root]. 怎样更新d值 d[i] = max(sum[i] , w[p]+s

poj 1655 and 3107 and 2378 树形dp(树的重心问题)

简单的树形dp,顺便学习了树的重心的概念,即以该点为根的树的最大子树的结点数最少. poj 1655: 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 20001; 7 int head[N]; 8 int balance[N]; 9 int child[N]; 10 int n, e; 11 12 struct

树形DP求树的重心 --SGU 134

令一个点的属性值为:去除这个点以及与这个点相连的所有边后得到的连通分量的节点数的最大值. 则树的重心定义为:一个点,这个点的属性值在所有点中是最小的. SGU 134 即要找出所有的重心,并且找出重心的属性值. 考虑用树形DP. dp[u]表示割去u点,得到的连通分支的节点数的最大值. tot[u]记录以u为根的这棵子树的节点数总和(包括根). 则用一次dfs即可预处理出这两个数组.再枚举每个点,每个点的属性值其实为max(dp[u],n-tot[u]),因为有可能最大的连通分支在u的父亲及以上

POJ 1655 Balancing Act[树的重心/树形dp]

Balancing Act 时限:1000ms Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or more trees. Define the balance of a node to be the size of the largest tree