CF1065F Up and Down the Tree
Posted bztminamoto
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1065F Up and Down the Tree相关的知识,希望对你有一定的参考价值。
题意:给你一棵树,你起点在1,1也是根节点,你每次可以选择去你子树的某个叶子节点,也可以选择,从叶子节点返回距离不超过k的一个根,也就是说,你从1开始,向下跳,选择一个叶子(就是没有子树的节点),然后可以选择一个距离小于等于k的点跳回去,然后继续跳下去再跳上来,问你最多能去多少个叶子节点,n<=1e6
大概的意思就是树形dp,$h[u]$表示$u$点到最近的叶子结点的距离,$dp[u]$表示$u$点最多能到的叶子的数量,$a[u]$表示从$u$跳下去又能跳回来的最多的点数
然后大概的思路就是从下往上考虑,先把子树里跳了能回来的节点全都跳一遍,然后再跳下去永远不回来
然后似乎是$h[u]>=k$的时候把$a[u]$设为$0$,因为它对父亲已经不会有贡献了
我的理解的话,就是把子树里所有跳下去能回来的节点单独记录,然后判断一下跳下去就回不来的方法哪一个更优,然后能回来的跳完之后就跳下去永远不会来就好了
1 //minamoto 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 5 char buf[1<<21],*p1=buf,*p2=buf; 6 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} 7 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} 8 inline int read(){ 9 #define num ch-‘0‘ 10 char ch;bool flag=0;int res; 11 while(!isdigit(ch=getc())) 12 (ch==‘-‘)&&(flag=true); 13 for(res=num;isdigit(ch=getc());res=res*10+num); 14 (flag)&&(res=-res); 15 #undef num 16 return res; 17 } 18 const int N=1e6+5,inf=0x3f3f3f3f; 19 int head[N],Next[N],ver[N],tot; 20 inline void add(int u,int v){ 21 ver[++tot]=v,Next[tot]=head[u],head[u]=tot; 22 } 23 int dp[N],a[N],h[N],n,k; 24 void dfs(int u){ 25 h[u]=inf; 26 for(int i=head[u];i;i=Next[i]){ 27 int v=ver[i];dfs(v); 28 cmin(h[u],h[v]+1),a[u]+=a[v],cmax(dp[u],dp[v]-a[v]); 29 } 30 dp[u]+=a[u]; 31 if(h[u]==inf) dp[u]=a[u]=1,h[u]=0; 32 if(h[u]>=k) a[u]=0; 33 } 34 int main(){ 35 // freopen("testdata.in","r",stdin); 36 n=read(),k=read(); 37 for(int i=2,fa;i<=n;++i) 38 fa=read(),add(fa,i); 39 dfs(1); 40 printf("%d ",dp[1]); 41 return 0; 42 }
以上是关于CF1065F Up and Down the Tree的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces1065F Up and Down the Tree 树形DP
6-8 Percolate Up and Down(20 分)
AAAI2022Close the Loop: A Unified Bottom-Up and Top-Down Paradigm for Joint Image Deraining...译读笔记