题目链接:

https://cn.vjudge.net/problem/URAL-1018

题目大意:

给你一棵树,每条边有一个边权,求以1为根节点,q条边的子数(q+1个点),边权和至最大。

解题思路:

dp[root][j], 表示以root为根节点,保留j个节点的最大边权和。

dp[root][j]=max(dp[root][j],dp[root][j-t]+dp[son][t]+len);

t的范围从1到j - 1,因为每个点从dp[][1]开始更新

 #include<bits/stdc++.h>
using namespace std;
const int maxn = + ;
typedef long long ll;
struct node
{
int v, w;
node(){}
node(int v, int w):v(v), w(w){}
};
vector<node>Map[maxn];
int num[maxn];//num[i]表示以i节点为root的子树中的点的数目
int dp[maxn][maxn];//dp[i][j]表示以i节点为root的子树中只有j条边最大权值
void dfs(int root, int fa)
{
num[root] = ;
for(int i = ; i < Map[root].size(); i++)
{
int v = Map[root][i].v, w = Map[root][i].w;
if(v == fa)continue;//不可回溯
dfs(v, root);//先将儿子信息更新好
num[root] += num[v];//root子树中当前的节点数目
for(int j = num[root]; j >= ; j--)//更新父节点的dp
{
for(int k = ; k < j && k <= num[v]; k++)//k不能等于j,k=j时说明root的点数目为0
dp[root][j] = max(dp[root][j], dp[root][j - k] + dp[v][k] + w);
}
}
}
int main()
{
int n, k;
while(scanf("%d%d", &n, &k) != EOF)
{
memset(dp, , sizeof(dp));
for(int i = ; i < n; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
Map[u].push_back(node(v, w));
Map[v].push_back(node(u, w));
}
dfs(, -);
cout<<dp[][k + ]<<endl;//包含k条边,也就是k+1个点
}
return ;
}

最新文章

  1. C语言新文法
  2. 数据库dump导入
  3. cmd 窗口配置mysql数据库
  4. SQLite的37个核心函数
  5. JPA概要
  6. 使用MWC四轴起飞侧翻解决方法
  7. Codeforces Round #254 (Div. 2) DZY Loves Chemistry【并查集基础】
  8. MongoDB的.Net驱动
  9. Java关键字transient和volatile小结(转)
  10. Java中StringBuffer类append方法的使用
  11. EntityFrameWork实现部分字段获取和修改(含源码)
  12. dojo中表格行隐藏出错
  13. 【55】java异常机制剖析
  14. error: src refspec XXX matches more than one
  15. [SDOI2013] 直径
  16. Oracle之with as和update用法
  17. 图之强连通、强连通图、强连通分量 Tarjan算法
  18. nodejs+mysql入门实例(增)
  19. AtomicBoolean
  20. js冒泡法和数组转换成字符串

热门文章

  1. JSON 教程
  2. 一、cent OS安装配置JDK
  3. 撩课-Java每天5道面试题第18天
  4. JS中数组和对象的区别
  5. CentOS网卡显示为__tmpxxxxxxxx
  6. web前端面试题(持续更新)
  7. 基于 Web 的 Go 语言 IDE - Wide 1.5.1 发布!
  8. MongoDB Limit/限制记录
  9. weex常用属性梳理
  10. netstat统计