一棵n个点的有根树,1号点为根,相邻的两个节点之间的距离为1。树上每个节点i对应一个值k[i]。每个点都有一个颜色,初始的时候所有点都是白色的。
你需要通过一系列操作使得最终每个点变成黑色。每次操作需要选择一个节点i,i必须是白色的,然后i到根的链上(包括节点i与根)所有与节点i距离小于k[i]的点都会变黑,已经是黑的点保持为黑。问最少使用几次操作能把整棵树变黑。
第一行一个整数n (1 ≤ n ≤ 10^5) 接下来n-1行,每行一个整数,依次为2号点到n号点父亲的编号。 最后一行n个整数为k[i] (1 ≤ k[i] ≤ 10^5) 样例解释: 对节点3操作,导致节点2与节点3变黑 对节点4操作,导致节点4变黑 对节点1操作,导致节点1变黑
一个数表示最少操作次数
4 1 2 1 1 2 2 1
3
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> tree[100005];
int v[100005],res,deep[100005],fa[100005],ch[100005];
void dfs(int);
int main(){
int N,i,x;
//freopen("input.txt","r",stdin);
for(scanf("%d",&N),i=2;i<=N;i++){
scanf("%d",&x);
tree[x].push_back(i);
}
for(i=1;i<=N;i++) scanf("%d",&v[i]);
dfs(1);printf("%d\n",res);
}
void dfs(int x){
fa[x]=deep[x]-v[x]+1;
ch[x]=1e9;
for(int i=0;i<tree[x].size();i++){
deep[tree[x][i]]=deep[x]+1;
dfs(tree[x][i]);
fa[x]=min(fa[x],fa[tree[x][i]]);
ch[x]=min(ch[x],ch[tree[x][i]]);
}
if(ch[x]>deep[x]) res++,ch[x]=fa[x];
}
// memo[i][0]: 以i节点为根的子树所需最少次数
// memo[i][1]: 以i节点为根的子树中所有节点能到达的最大范围
// memo[i][2]: 以i节点为根的子树中实际能够覆盖的范围,注意该值并不与最大值有关
// 该实现方法由力扣跳跃游戏的思路而来
#include <iostream>
#include <vector>
#include <functional>
#include <cmath>
#include <climits>
using namespace std;
struct TreeNode {
int k;
vector<int> children;
};
int main() {
int n;
cin >> n;
vector<TreeNode> tree(n + 1, {0});
vector<vector<int>> memo(n + 1, {0, 0, 0});
function<vector<int>(int)> dfs = [&] (int idx) -> vector<int> {
if(memo[idx][1] != 0) {
return memo[idx];
}
if(tree[idx].children.empty()) {
memo[idx] = {1, tree[idx].k, tree[idx].k};
}
memo[idx][1] = tree[idx].k;
for(auto child: tree[idx].children) {
auto childRes = dfs(child);
int childLimit = childRes[2] - 1;
if(memo[idx][2] < childLimit) {
memo[idx][2] = childLimit;
}
memo[idx][0] += memo[child][0];
memo[idx][1] = max(memo[idx][1], memo[child][1] - 1);
}
if(memo[idx][2] == 0) {
memo[idx][0] += 1;
memo[idx][2] = memo[idx][1];
}
return memo[idx];
};
for(int i = 2; i <= n; ++i) {
int p;
cin >> p;
tree[p].children.push_back(i);
}
for(int i = 1; i <= n; ++i) {
int k;
cin >> k;
tree[i].k = k;
}
for(int i = 1; i <= n; ++i) {
dfs(i);
}
cout << memo[1][0];
}
// 64 位输出请用 printf("%lld")