题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17662

题意:给一棵边有权值的二叉树,节点编号为1~n,1是根节点。求砍掉一些边,只保留q条边,这q条边构成的子树的根节点要求是1,求这颗子树的最大权值。

分析:1.dp[u][i]表示已以u为根节点的子树,保留了i个节点的最大权值。每条边的权值,把它看作是连接的两个节点中的儿子节点的权值。那么总共要保留m+1个节点。

所以有:dp[u][i]=max(dp[u][i],dp[v][k]+dp[u][i-k]+w).ans=dp[1][m+1].

2.dp[u][i]表示u为根节点的子树,保留了i个条边的最大权值。在以u点为根节点的子树中选择了k条边,那么u的儿子节点v代表的子树中至多选k-1条边,因为如果在v子树中选边,那么u到v的边必选。

所以有:dp[u][i]=max(dp[u][i],dp[u][i-k]+dp[v][k-1]+w).ans=dp[1][m].

方法1的代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define N 110
#define clr(a) (memset(a,0,sizeof(a)))
using namespace std;
struct edge
{
int v,w,next;
edge(){}
edge(int v,int w,int next):v(v),w(w),next(next){}
}e[*N];
int head[N],dp[N][N],num[N],tot,n,m;
void addedge(int u,int v,int w)
{
e[tot]=edge(v,w,head[u]);
head[u]=tot++;
}
void dfs(int u,int fa)
{
num[u]=;
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].v,w=e[i].w;
if(v==fa)continue;
dfs(v,u);
num[u]+=num[v];
for(int j=num[u];j>=;j--)
for(int k=;k<j&&k<=num[v];k++)//注意这里k<j.因为子树根节点u点必选,在子树节点中至多选j-1个
dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]+w);
}
}
int main()
{
int u,v,w;
while(scanf("%d%d",&n,&m)>)
{
memset(head,-,sizeof(head));
clr(dp);tot=;
for(int i=;i<n;i++)
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
dfs(,-);
printf("%d\n",dp[][m+]);
}
}

方法2的代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define N 110
#define clr(a) (memset(a,0,sizeof(a)))
using namespace std;
struct edge
{
int v,w,next;
edge(){}
edge(int v,int w,int next):v(v),w(w),next(next){}
}e[*N];
int head[N],dp[N][N],tot,n,m;
void addedge(int u,int v,int w)
{
e[tot]=edge(v,w,head[u]);
head[u]=tot++;
}
void dfs(int u,int fa)
{
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].v,w=e[i].w;
if(v==fa)continue;
dfs(v,u);
for(int j=m;j>=;j--)
for(int k=;k<=j;k++)
dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k-]+w);
}
}
int main()
{
int u,v,w;
while(scanf("%d%d",&n,&m)>)
{
memset(head,-,sizeof(head));
clr(dp);tot=;
for(int i=;i<n;i++)
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
dfs(,-);
printf("%d\n",dp[][m]);
}
}

ural1018(树形dp)的更多相关文章

  1. URAL1018 Binary Apple Tree(树形DP)

    题目大概说一棵n结点二叉苹果树,n-1个分支,每个分支各有苹果,1是根,要删掉若干个分支,保留q个分支,问最多能保留几个苹果. 挺简单的树形DP,因为是二叉树,都不需要树上背包什么的. dp[u][k ...

  2. 树形DP小结

    树形DP1.简介:树是一种数据结构,因为树具有良好的子结构,而恰好DP是从最优子问题更新而来,那么在树上做DP操作就是从树的根节点开始深搜(也就是记忆化搜索),保存每一步的最优结果.tips:树的遍历 ...

  3. 树形 DP 总结

    树形 DP 总结 本文转自:http://blog.csdn.net/angon823/article/details/52334548 介绍 1.什么是树型动态规划 顾名思义,树型动态规划就是在“树 ...

  4. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  5. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  6. 【BZOJ-4726】Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  7. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  8. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

  9. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  10. POJ2342 树形dp

    原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...

随机推荐

  1. perl 登陆电信猫

    登陆电信猫: use LWP::UserAgent; use HTTP::Date qw(time2iso str2time time2iso time2isoz); use Net::Ping; u ...

  2. Windows 8 动手实验系列教程 实验5:进程生命周期管理

    动手实验 实验5:进程生命周期管理 2012年9月 简介 进程生命周期管理对构建Windows应用商店应用的开发者来说是需要理解的最重要的概念之一.不同于传统的Windows应用(它们即使在后台仍然继 ...

  3. vc 制作图片资源dll

    方法一: 使用纯WIN32 DLL方法封装纯资源第一步,通过VS2005建立WIN32 DLL 空工程第二步,设置配置属性->链接器->高级->无入口点(是/NOENTRY)设置配置 ...

  4. centos6安装bt工具transmission

    centos6 install transmission 1.  安装所需的组件: yum -y install gcc gcc-c++ m4 make automake libtool gettex ...

  5. JAVA编程心得-JAVA实现CRC-CCITT(XMODEM)算法

    CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定. 1 byte checksum CRC ...

  6. IOS不用AutoLayout也能实现自己主动布局的类(3)----MyRelativeLayout横空出世

    对于IOS开发人员来说,在自己主动布局出现前仅仅能通过计算和设置frame的值来处理.这样设置位置时就会出现非常多硬编码,同一时候在屏幕旋转和不同屏幕之间适配时须要编码又一次调整位置和尺寸,我们也能够 ...

  7. linux-sfdisk 使用方法

    功能说明:硬盘分区工具程序. 语 法:sfdisk [-?Tvx][-d <硬盘>][-g <硬盘>][-l <硬盘>][-s <分区>][-V < ...

  8. GNU GPL介绍

    怎样在程序中使用GNU许可证       不管使用哪种许可证,使用时须要在每一个程序的源文件里加入两个元素:一个版权声明和一个复制许可声明.说明该程序使用GNU许可证进行授权.另外在声明版权前应该说明 ...

  9. ubuntu12 环境下编译freerdp

    有时候需要从linux环境下远程连接到windows的环境,可以采用freerdp.freerdp是一个linux下开源的工具,在Ubuntu下可以直接用 apt-get install freerd ...

  10. 解决ScrollView中的ListView无法显示全

    问题描述: ListView加入到ScrollView中之后,发现只能显示其中一条,具体原因得看一下源代码.现在先贴一下方案 (转自:http://blog.csdn.net/hitlion2008/ ...