牛客:黑白树
题解:本题我们首先会意识到叶子结点必须要选,难在递归回溯的时候如何贪心使其结果最优,当我们选了一个结点,那么每当我们再向上回溯一层的时候,就会消耗该所选结点的一个值,即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;
}