人品问题 树形dp
网上出现了一种高科技产品——人品测试器。只要你把你的真实姓名输入进去,系统将自动输出你的人品指数。把儿不相信自己的人品为0。经过了许多研究后,把儿得出了一个更为科学的人品计算方法。这种方法的理论依据是一个非常重要的结论:人品具有遗传性。因此,一个人的人品完全由他的祖先决定。把儿提出的人品计算方法相当简单,只需要将测试对象的k个祖先的人品指数(可能为负数)加起来即可。选择哪K个祖先可以由测试者自己决定,但必须要满足这个要求:如果除自己的父母之外的某个祖先被选了,那么他的下一代必需要选(不允许跳过某一代选择更远的祖先,否则将失去遗传的意义)。
非常不幸的是,把儿测试了若干次,他的人品值仍然不能为一个正数。现在把儿需要你帮助他找到选择祖先的最优方案,使得他的人品值最大。
输入格式:
数据的第一行是两个用空格隔开的正整数n和k,其中n代表把儿已知的家谱中共有多少人(包括把儿本身在内),k的意义参见问题描述。
数据的第二行有n-1个用空格隔开的整数(可能为负),这些数的绝对值在2^15以内。其中,第i个数表示编号为i+1的人的人品值。我们规定,编号为1的人是把儿。
接下来n行每行有两个用空格隔开的数,其中第i行的两个数分别表示第i个人的父亲和母亲的编号。如果某个人的父亲或母亲不在这个家谱内,则在表示他的父亲或母亲的编号时用0代替。
输入数据中除把儿以外的所有人都是把儿的祖先,他们都会在输入数据中作为父亲或母亲被描述到。输入数据中每个人都不可能同时作为多个人的父亲或者是母亲。
输出格式:
将把儿能够得到的最大人品值输出
样例输入:
6 3
-2 3 -2 3 -1
2 3
4 5
0 6
0 0
0 0
0 0
样例输出:
4
数据范围:
对于50%的数据,n<=10;
对于100%的数据,n<=100。
时间限制:
1000
空间限制:
10240
做法:
ans[i][j]表示编号为i的人选j个祖先及自身的最大人品值
ans[i][j]=a[i]+max{ans[lc[i]][k]+ans[rc[i]][j-k-1]}
(0<=k<=j-1,num[lc[i]]>=k,num[rc[i]]>=j-k-1 --> k>=j-num[rc[i]]-1)
直接设定ans[0][0]=0即可,不用加特判
#include<cstdio>
#include<cstring>
typedef long long LL;
bool vis[];
LL n,k;
LL lc[],rc[],a[];
LL dp[][];
LL num[];//记录某结点及所有后代结点的总数量
LL min(LL x,LL y)
{
return x>y?y:x;
}
LL max(LL x,LL y)
{
return x>y?x:y;
}
LL dfs(LL x)
{
num[x]=;
if(lc[x]) num[x]+=dfs(lc[x]);
if(rc[x]) num[x]+=dfs(rc[x]);
return num[x];//改成这样提速效果不大
}
/*
LL dfs(LL x)
{
if(x==0) return 0;
num[x]=dfs(lc[x])+dfs(rc[x])+1;
return num[x];
}
LL dp(LL i,LL j)
{
if(j==0) return 0;
if(j==1) return a[i];
LL k,ans1=-0x3f3f3f3f;
for(k=max(j-num[rc[i]]-1,0);k<=min(num[lc[i]],j-1);k++)
ans1=max(ans1,dp(lc[i],k)+dp(rc[i],j-k-1));
return ans1+a[i];//这样写T两个点
}//下面的貌似是类似常数优化的,不知道为什么差距这么大
//理论上不用记忆化,毕竟这个树形结构没有重叠子问题,也许是减少了函数调用次数
*/
void Dp(LL x)//直接处理完一个结点选任意数量子结点的答案
//这样写全部0ms过
{
dp[x][]=a[x];
dp[x][]=;
if(lc[x]) Dp(lc[x]);
if(rc[x]) Dp(rc[x]);
int i,j;
for(i=;i<=num[x];i++)
{
for(j=max(i-num[rc[x]]-,);j<=min(num[lc[x]],i-);j++)
dp[x][i]=max(dp[x][i],dp[lc[x]][j]+dp[rc[x]][i-j-]);
//傻了,曾经写成dp[x][i]=max(dp[lc[x]][j],dp[rc[x]][i-j-1]);了
dp[x][i]+=a[x];//曾经忘记//曾经将a[x]写成a[i]
}
}
/*
void Dp(LL x)//直接处理完一个结点选任意数量子结点的答案
//这样写也是全部0ms过
{
//dp[x][1]=a[x];
dp[x][0]=0;
if(lc[x]) Dp(lc[x]);
if(rc[x]) Dp(rc[x]);
int i,j;
for(i=1;i<=num[x];i++)
{
for(j=max(i-num[rc[x]]-1,0);j<=min(num[lc[x]],i-1);j++)
dp[x][i]=max(dp[x][i],dp[lc[x]][j]+dp[rc[x]][i-j-1]);
dp[x][i]+=a[x];
}
}
*/
int main()
{
LL i;
memset(dp,,sizeof(dp));
scanf("%lld%lld",&n,&k);
for(i=;i<=n;i++)
scanf("%lld",&a[i]);
for(i=;i<=n;i++)
scanf("%lld%lld",&lc[i],&rc[i]);
dfs();
//dp[0][1]=0;//不需要,因为num[0]=0,与0有关的最多只涉及到dp[0][0]
dp[][]=;
Dp();
printf("%lld",dp[][k+]);//算上自己共要选k+1人
return ;
}
人品问题 树形dp的更多相关文章
- poj3417 LCA + 树形dp
Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4478 Accepted: 1292 Descripti ...
- COGS 2532. [HZOI 2016]树之美 树形dp
可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...
- 【BZOJ-4726】Sabota? 树形DP
4726: [POI2017]Sabota? Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 128 Solved ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- 树形DP
切题ing!!!!! HDU 2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...
- BZOJ 2286 消耗战 (虚树+树形DP)
给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...
- POJ2342 树形dp
原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...
- hdu1561 The more, The Better (树形dp+背包)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...
- bzoj2500: 幸福的道路(树形dp+单调队列)
好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...
随机推荐
- angularjs学习之八(angularjs中isolate scope的使用)
angular js中指令directive有个特别实用的东西,那就是 isolate scope (被隔离的scope) 关于详细他和全局的scope 有什么差别.能够參考以下这篇博文: Angul ...
- WPF新手之如何将数据绑定到TreeView
看过许多例子,全是绑定到类的,没人说如何绑定到某个对象,偏偏我这个绝对的新手就是要绑定到一个对象,只能自己摸索了: 首先要将数据绑定到容器,有以下几个默认条件:①元数据必须包装在List或者Obser ...
- MD5加密实现类不是Windows平台下联邦信息处理标准验证过的加密算法的一部分
在.NET应用程序中,MD5CryptoServiceProvider实例化时,造成This implementation is not part of the Windows Platform FI ...
- Cooperating sequential processes》,这篇论文提出了大名鼎鼎的概念信号量,Java里面用于线程同步的wait/notify也是信号量的一种实现。
闲话高并发的那些神话,看京东架构师如何把它拉下神坛 https://mp.weixin.qq.com/s/lAqn8CfSRta9iSvOR1Le6w
- XMU C语言程序设计实践(5)
• 使用动态链表完成一个简单的商品库存信息管理系统. • 商品信息包括如下字段:商品号.商品名称.商品库存 • 函数 create:接收用户输入的商品号和商品名称的 ...
- CUE 文件格式说明
CUE 文件,即 CUESheets ,光盘镜像辅助文件.通常用于光盘刻录.音乐播放等等. 比如用 EAC 刻录CD光盘,或者用 Foobar2000 播放整轨音乐文件. CUE 文件是非常好的音乐专 ...
- sublime text3的安装使用
1.下载网址:https://www.sublimetext.com/3 2.编译环境配置:https://jingyan.baidu.com/article/6f2f55a155a7d1b5b93e ...
- SocketErrorCode:10022
在编写.net的网络服务器时,我使用了裸socket来实现.在windows上,或者在linux上通过.net core来跑时都没有什么问题,但是通过mono运行调用socket.Bind()时却总是 ...
- ubuntu中使用apt-get安装zbar
apt-get是linux中常用的shell命令,适用于deb包管理式的操作系统,主要用于自动从互联网的软件仓库中搜索.安装.升级.卸载软件或操作系统.apt-get命令一般需要root权限执行,所以 ...
- Linux限制端口
设置防火墙 iptables -a input -p 协议 -s 可以访问ip -dport端口 -j ACCEPT