题意:有一棵树,树上每个结点都有一个权值,求恰好包含k个结点的子树的最大权值。

设dp[i][j]为以结点i为根的树中包含j个结点的子树的最大权值,则可以把这个结点下的每棵子树中所包含的所有子树的大小当做物品的重量,对应的最大权值当做物品的价值,则相当于在它的每颗子树的所有物品中任选一个进行更新,对每个状态取最大价值。

状态转移方程:$dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k])$

注:由于每棵子树下只能选一件物品,所以应当先枚举状态再枚举物品,这样就避免了同一棵子树下状态的累加。

复杂度$O(n^3)$,可用siz数组确定上界优化到$O(n^2)$。

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=+;
int hd[N],a[N],ne,n,k,dp[N][N],siz[N];
struct E {int v,nxt;} e[N<<];
void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
void dfs(int u,int fa) {
memset(dp[u],-,sizeof dp[u]);
siz[u]=,dp[u][]=a[u];
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
if(v==fa)continue;
dfs(v,u);
for(int j=siz[u]; j>=; --j)if(~dp[u][j])
for(int k=; k<=siz[v]; ++k)if(~dp[v][k])
dp[u][j+k]=max(dp[u][j+k],dp[u][j]+dp[v][k]);
siz[u]+=siz[v];
}
} int main() {
while(scanf("%d%d",&n,&k)==) {
memset(hd,-,sizeof hd),ne=;
for(int i=; i<n; ++i)scanf("%d",&a[i]);
for(int i=; i<n-; ++i) {
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs(,-);
int ans=;
for(int i=; i<n; ++i)ans=max(ans,dp[i][k]);
printf("%d\n",ans);
}
return ;
}

最新文章

  1. ASP.NET MVC Model绑定的简单应用
  2. nodejs 框架安装生成app
  3. 黑马程序员——有关protocol代理模式的举例说明
  4. C#复习,输入学生信息排列成绩
  5. 【转】Java 中字符串的格式化
  6. Visual Studio 启动加速
  7. 浅析linux中的fork、vfork和clone
  8. CDockablepane风格设置
  9. 应用activeMQ消息中间件同步索引库
  10. oracle查询相关语句
  11. java做图片点击文字验证码
  12. BZOJ3932 主席树
  13. 滚动锚定(Scroll Anchoring)- 让视口内容不再因视口上方 DOM 元素的高度变化而产生跳动
  14. 洛谷P2765魔术球问题 最小路径覆盖
  15. linux位数查看
  16. mysql分区分表讲解
  17. 编写dll时的内存分配策略
  18. 第一篇Docker博文
  19. top命令参数
  20. Sublime Text2/3怎样在Mac OSX中配置CTags插件

热门文章

  1. user_admin
  2. 预防SQL注入攻击
  3. 【转】Linux rpm 安装卸载操作
  4. $《第一行代码:Android》读书笔记——第9章 服务
  5. linux ip别名和辅助ip地址
  6. Linux挂载第二块硬盘操作方法
  7. spark总结5 RDD
  8. RealThinClient SDK 学习笔记(1)
  9. 域名注册中EAP期间是什么意思
  10. jsp连接sqlServer数据库教程、jsp连接sqlServer数据库报ClassNotFoundException异常