https://ac.nowcoder.com/acm/problem/13249(树形dp)

牛客:黑白树
题解:本题我们首先会意识到叶子结点必须要选,难在递归回溯的时候如何贪心使其结果最优,当我们选了一个结点,那么每当我们再向上回溯一层的时候,就会消耗该所选结点的一个值,即k[i]-1,而且每次我们还要不断更新通过该节点向上最远到达的长度,如果上一次选的结点已经消耗完,我们就从该节点子树的其他结点再找一个最大的k的结点来继续向上延续,主要是代码不好实现,在这里我们需要维护两个数组。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
const int maxn=1e5+10;

int read() {
    int X=0,w=1; char c=getchar();
    while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
    while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();
    return X*w;
}
int n;
int k[maxn];
int dp[maxn];
vector<int> G[maxn];
int ans=0;
void dfs(int u,int fa)
{
    for(int i=0;i<G[u].size();i++){
        int to=G[u][i];
        if(to==fa)continue;
        dfs(to,u);
        k[u]=max(k[u],k[to]-1);
        dp[u]=max(dp[u],dp[to]-1);
    }
    if(!dp[u]){
        dp[u]=k[u];
        ans++;
    }
}
int main()
{
   scanf("%d",&n);
   for(int i=2;i<=n;i++){
    int u;
    scanf("%d",&u);
    G[u].push_back(i);G[i].push_back(u);
   }
    for(int i=1;i<=n;i++){
    scanf("%d",&k[i]);
    }
   dfs(1,0);
   printf("%d\n",ans);
   return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值