一棵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")