刷油漆(树形DP)

问题描述:

有一棵树,树上节点编号1~n,其中节点1为根节点,树上的每个节点有其对应的一个价值。现在要减掉一些枝桠,只留下m个节点的一棵树(必须包含根节点),为这m个节点着色,约束条件是要使剩下m个节点的价值之和最大化。

算法思路:

状态定义:dp[x][j]表示以节点x为根的子树中,着色节点数目为j时,从这棵子树中所能获得的最大价值。那么dp[1][m]即为所求。

状态转移:设节点y为节点x的子节点,那么dp[x][j] = max(dp[x][j], dp[y][k]+dp[x][j-k]),其中1<=k<j。

整体思路类似于完全背包。

我的代码:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <vector>
 4 #include <cstring>
 5
 6 using namespace std;
 7
 8 #define MAXN 105
 9
10 int dp[MAXN][MAXN], n, m, v[MAXN];
11 bool vis[MAXN];
12 struct Tree
13 {
14     vector<int> t[MAXN];
15     void init(int n)
16     {
17         for(int i=1; i<=n; ++i) t[i].clear();
18         memset(&vis[1], 0, n);
19     }
20     void addEdge(int a, int b)
21     {
22         t[a].push_back(b);
23         t[b].push_back(a);
24     }
25     void solute(int x)
26     {
27         vis[x] = true;
28         memset(dp[x], 0, (m+1)*sizeof(int));
29         dp[x][1] = v[x];
30         for(int i=0; i<t[x].size(); ++i)
31         {
32             int y = t[x][i];
33             if(!vis[y])
34             {
35                 solute(y);
36                 for(int j=m; j>=2; --j) //注意这里的遍历顺序
37                 for(int k=1; k<j; ++k) dp[x][j] = max(dp[x][j], dp[x][j-k]+dp[y][k]);
38             }
39         }
40     }
41 }tree;
42
43 int main()
44 {
45     while(cin>>n>>m)
46     {
47         for(int i=1; i<=n; ++i) cin>>v[i];
48         tree.init(n);
49         for(int i=0; i<n-1; ++i)
50         {
51             int a, b;
52             cin>>a>>b;
53             tree.addEdge(a, b);
54         }
55         tree.solute(1);
56         cout<<dp[1][m]<<endl;
57     }
58
59     return 0;
60 }

题目来源:http://hihocoder.com/problemset/problem/1055

时间: 2024-08-08 19:14:37

刷油漆(树形DP)的相关文章

hihoCoder #1055 : 刷油漆 [ 树形dp ]

传送门 结果:Accepted     提交时间:2015-05-11 10:36:08 #1055 : 刷油漆 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho有着一棵灰常好玩的树玩具!这棵树玩具是由N个小球和N-1根木棍拼凑而成,这N个小球都被小Ho标上了不同的数字,并且这些数字都是处于1..N的范围之内,每根木棍都连接着两个不同的小球,并且保证任意两个小球间都不存在两条不同的路径可以互相到达.没错,这次说的还是这棵树玩具的故事! 小Ho的树玩具

HihoCoder 1055 : 刷油漆 树形DP第一题

刷油漆 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho有着一棵灰常好玩的树玩具!这棵树玩具是由N个小球和N-1根木棍拼凑而成,这N个小球都被小Ho标上了不同的数字,并且这些数字都是处于1..N的范围之内,每根木棍都连接着两个不同的小球,并且保证任意两个小球间都不存在两条不同的路径可以互相到达.没错,这次说的还是这棵树玩具的故事! 小Ho的树玩具的质量似乎不是很好,短短玩了几个星期,便掉漆了! "简直是一场噩梦!"小Ho拿着树玩具眼含热泪道

hiho 1055 刷油漆 树形dp

一个简单的树上的背包问题. 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <algorithm> 7 #include <string> 8 #include <queue> 9 #include <stack>

hihoCoder1055.刷油漆——树形Dp+01背包

http://hihocoder.com/problemset/problem/1055 一棵有根树,包含根节点1,选择M个连续的节点,使得权值最大 dp[u][j] 表示以i为根的子树中,选择包含根节点的j个连续节点所能获得的最大权值 枚举子节点选择的个数,儿子节点选择的个数,当做01背包 #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include

hihoCoder hiho一下 第十二周 #1055 : 刷油漆 (树上DP)

思路:树上的动态规划.只能刷部分节点数m,总节点数n.如果m>=n那么就可以全刷了,那就不用任何算法了.如果m<n那么就要有取舍了.用DP思路,记录下每个节点如果获得到1~m个选择所能获得的最大权值.这里的树不仅仅是二叉,可能是多叉.所以一个节点怎么合理分配给每个孩子的空间大小很关键,当第一个孩子获得了1空间,那么后面的孩子所能获得的空间就要少一个了.这样穷举每个孩子能得到的空间,来求当前节点的最大权值,会有很多种可能,m!.不用这么做. 递归步骤: 假设状态记录为 dp[节点][该节点所获得

刷题总结——二叉苹果树(ssoj树形dp+记忆化搜索)

题目: 题目背景 URAL:http://acm.timus.ru/problem.aspx?space=1&num=1018 题目描述 有一棵苹果树,如果树枝有分叉,一定是分 2 叉(就是说没有只有 1 个儿子的结点,这棵树共有N 个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置.下面是一颗有 4 个树枝的树:         2    5          \ /              3    4         

【刷题】【树形dp】

1>树上染色 (题解复制自luogu) 题目要求将k个点染成黑色,求黑点两两距离及白点两两距离,使他们之和最大. 我们可以将距离转化为路径,然后再将路径路径拆分成边,就可以记录每条边被经过的次数,直接计算即可. 很简单对吧?那么问题来了,距离转化为路径好理解,路径拆为边也好说,可是每条边被经过的次数怎么计算呢? 我们可以这样想,我们任意取两个同色的点,对于每一条边,若不在这两个点的路径上,我们自然不考虑,若是在两个点的路径上,那么这条边的计数加一.我们可以转换一下,若是两个点在边的一侧,则不影响

hiho_1055_刷油漆

题目大意 一棵树,每个节点都有相应的value值.从根开始选择M个节点相互连通,使得这些节点的value值之和最大. 题目链接:[刷油漆][1] 题目分析 典型的树形dp,dp[i][j] 表示以节点i为根的子树中选择j个节点(从i节点出发)相互连通,所能达到的节点value之和的最大值.可以很容易知道, dp[root][k] = max{dp[ch1][k1] + dp[ch2][k2] + .. dp[cht][kt]}. 即将k-1个节点分配给 根节点root的t个子节点,其中 k1 +

刷油漆

刷油漆 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho有着一棵灰常好玩的树玩具!这棵树玩具是由N个小球和N-1根木棍拼凑而成,这N个小球都被小Ho标上了不同的数字,并且这些数字都是处于1..N的范围之内,每根木棍都连接着两个不同的小球,并且保证任意两个小球间都不存在两条不同的路径可以互相到达.没错,这次说的还是这棵树玩具的故事! 小Ho的树玩具的质量似乎不是很好,短短玩了几个星期,便掉漆了! “简直是一场噩梦!”小Ho拿着树玩具眼含热泪道. “这有

poj 4045 Power Station(初涉树形dp)

http://poj.org/problem?id=4045 大致题意:有n个村庄,求将发电站建在哪一个村庄使得花费最少.这是一个无向无环图.简化一下就是求一个节点使它到其他所有节点的距离和最小. 起初一直在向最短路上靠,但因为节点和边数太大,必定TLE.然后无比强大的啸神随便写了两个dfs就过掉了,简直膜拜.赛后搜了搜题解,发现这是道树形dp.sad,真的要好好刷dp了. 大体思路是将这个无向无环图看做一个树,我们就在这个树上进行动态规划.首先先随便拿一个节点看做根节点(假设节点1),计算出它