Educational Codeforces Round 52 (Rated for Div. 2) F. Up and Down the Tree 树型DP

本文介绍了一种利用树形动态规划(DP)解决特定路径限制下的最大叶子节点访问数量问题的方法。在一个给定的树状结构中,从根节点出发,考虑在规定距离k内可往返的叶子节点,通过优化算法确定能访问的最大叶子节点数。核心思路在于自底向上计算每个节点的最优解,特别关注节点到最近叶子节点的距离以及该节点可贡献的叶子节点数量。

题面

题意:给你一棵树,你起点在1,1也是根节点,你每次可以选择去你子树的某个叶子节点,也可以选择,从叶子节点返回距离不超过k的一个根,

         也就是说,你从1开始,向下跳,选择一个叶子(就是没有子树的节点),然后可以选择一个距离小于等于k的点跳回去,然后继续跳下去再跳上来,问你最多能去多少个叶子节点,n<=1e6

题解:大概分析就是要找一颗子树,然后叶子节点的到主链上的距离小于等于k的尽量多,这样我们就可以跳下跳上的跳很多次了

         h[u]表示u到最近的叶子节点的距离,f[u]表示u能去到最多叶子节点个数(f[1]也就是答案),a[u]表示如果从u跳下去又能跳回来的叶子节点个数

         大概描述我们的想法就是,对于每个点,我们先访问它的子树,自下而上,告诉他们,哪些叶子可以跳回来,对于每个点的答案就是,能跳回来的都跳,最后再跳下去不回来

         所以对于那些h[u]>=k 的u,a[u]=0,为什么有等号,其实这个a是对他的父亲节点起作用的,他的父亲需要他的a,而他需要的是他的儿子节点.

        代码上,学习了台湾人一波,inf的使用和f[v]和a[v]的先减后加使得代码更简洁ORz

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 1000006
 4 #define inf ((int)1e9)
 5 int nex[N],head[N],gox[N];
 6 int a[N],f[N],h[N],n,k,x,p;
 7 void build(int a,int b)
 8 {
 9     p++;
10     nex[p]=head[a];
11     gox[p]=b;
12     head[a]=p;
13 }
14 void dfs(int u)
15 {
16     h[u]=inf;
17     for (int e=head[u];e;e=nex[e])
18     {
19         int v=gox[e];
20         dfs(v);
21         h[u]=min(h[u],h[v]+1);
22         a[u]+=a[v]; 
23         f[u]=max(f[u],f[v]-a[v]);
24     }
25     f[u]+=a[u];
26     if (h[u]==inf) 
27     {
28         h[u]=0;
29         f[u]=a[u]=1;
30     }
31     if (h[u]>=k) a[u]=0;
32 }
33 
34 int main()
35 {
36     scanf("%d%d",&n,&k);
37     for(int i=2;i<=n;++i)
38     {
39         scanf("%d",&x);
40         build(x,i);
41     }
42     dfs(1);
43     printf("%d",f[1]);
44     return 0;
45 }

 

转载于:https://www.cnblogs.com/qywhy/p/9776981.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值