P1676陶陶吃苹果 - vijos


描述

curimit知道陶陶很喜欢吃苹果。于是curimit准备在陶陶生日的时候送给他一棵苹果树。

curimit准备了一棵这样的苹果树作为生日礼物:这棵苹果树有n个节点,每个节点上有c[i]个苹果,这棵树高度为h。

可是,当curimit把这棵树给陶陶看的时候,陶陶却说:“今年生日不收礼,收礼只收节点数减高度不超过k的苹果树。”这下curimit犯难了,curimit送来的树枝繁叶茂,不满足节点数-高度≤k。于是curimit决定剪掉一些枝条,使得修剪过后的树满足节点数-高度≤k,但是curimit又想保留尽量多的苹果数目。curimit想请你帮他算算经过修剪后的树最多能保留多少个苹果。

注:
一, 节点1为树根,不能把它剪掉。

二, 1个节点的树高度为1。
格式
输入格式

输入文件的第一行为两个整数n,k分别表示这棵树有n个节点,修剪后的树节点数-高度≤k。

第二行开始到第n+1行,每行有两个数,第i+1行的两个数father[i]和c[i]分别表示节点i的父亲是father[i]和节点i处有c[i]个苹果。

规定:节点1的父亲为0。
输出格式

输出文件仅包含一行,ans,表示在满足修建后的树节点数-高度≤k的条件下,最多能保留多少个苹果。
样例1
样例输入1[复制]

    5 1
    0 1
    1 1
    1 3
    2 10
    3 4

样例输出1[复制]

    15

限制

全部1秒
提示

【约定】
对于10%的数据, n≤10
对于30%的数据, n≤100 0≤k≤20
对于100%的数据,n≤4000 0≤k≤=500

神啦,树形依赖背包还可以出成这样

我们回忆我们怎么做树形依赖背包的

s是i的儿子,f[s]的初值为f[i],dfs(s),然后f[i,v]:=min(f[i,v],f[i,v-1]+a[s])

这样的话我们发现叶子节点存的f其实就是处理了这条链左边的节点所得到的信息

仔细观察题目条件,我们发现这个是树形依赖背包,但是有一条链免费,所以我们dfs两次,一次从左往右,一次从右往左

然后我们枚举免费的链,只枚举根到叶子节点的(1.我们只能保证叶子节点有上面这个性质2.免费的链当然是越深越好啦),然后更新答案

orz出题人

 

 1 const
 2     maxn=4040;
 3     maxk=550;
 4 var
 5     fl,fr:array[0..maxn,0..maxk]of longint;
 6     v:array[0..maxn,0..maxn]of longint;
 7     a,sum,f:array[0..maxn]of longint;
 8     n,k,ans:longint;
 9 
10 function max(x,y:longint):longint;
11 begin
12     if x>y then exit(x);
13     exit(y);
14 end;
15 
16 procedure dfsl(x:longint);
17 var
18     i,j:longint;
19 begin
20     sum[x]:=sum[f[x]]+a[x];
21     for i:=1 to v[x,0] do
22         begin
23             for j:=0 to k do
24                 fl[v[x,i],j]:=fl[x,j];
25             dfsl(v[x,i]);
26             for j:=1 to k do
27                 fl[x,j]:=max(fl[x,j],fl[v[x,i],j-1]+a[v[x,i]]);
28         end;
29 end;
30 
31 procedure dfsr(x:longint);
32 var
33     i,j:longint;
34 begin
35     for i:=v[x,0] downto 1 do
36         begin
37             for j:=0 to k do
38                 fr[v[x,i],j]:=fr[x,j];
39             dfsr(v[x,i]);
40             for j:=1 to k do
41                 fr[x,j]:=max(fr[x,j],fr[v[x,i],j-1]+a[v[x,i]]);
42         end;
43 end;
44 
45 procedure main;
46 var
47     i,x:longint;
48 begin
49     read(n,k);
50     for i:=1 to n do
51         begin
52             read(f[i],a[i]);
53             inc(v[f[i],0]);v[f[i],v[f[i],0]]:=i;
54         end;
55     dfsl(1);
56     dfsr(1);
57     for i:=1 to n do
58         if v[i,0]=0 then
59         for x:=0 to k do
60             ans:=max(ans,fl[i,x]+fr[i,k-x]+sum[i]);
61     writeln(ans);
62 end;
63 
64 begin
65     main;
66 end.
View Code

 

转载于:https://www.cnblogs.com/Randolph87/p/3799425.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值