感受
我真菜,居然做不出来
什么时候我可以变得强起来!
思路
看完题解后,恍然大悟。
对于一个一定不能由子树覆盖的点,那么这个点一定要染色。
那么染色一定是染这个点w吗?不是,其实可以染子树中的任意一点,只需要保证染完之后,假设染的是u,那么从u到w后的向上延伸距离最大(k[u] - (dep[u] - dep[w]).
题解在处理这个子问题时比我的想法简单不少,可以一直更新每一个节点的最大延伸距离,然后从而达到这个效果。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
struct edge{
int v, nex;
}e[maxn * 2];
int head[maxn], cnt, n;
int dp[maxn], k[maxn];///dp[i]表示i节点往上还可以最多走几步(走到的位置为必须染色时刻)
///k[i]表示以i为当前根的子树所有节点到达i后还可以往上走步数的最大值
void add_edge(int u, int v){
cnt++;
e[cnt] = (edge){v, head[u]};
head[u] = cnt;
}
int ans;
void dfs(int u, int f){
int v;
for(int i = head[u]; i > 0; i = e[i].nex){
v = e[i].v;
if(v == f) continue;
dfs(v, u);
dp[u] = max(dp[u], dp[v] - 1);
k[u] = max(k[u], k[v] - 1);
}
if(!dp[u]){
ans++;
dp[u] = k[u];
}
}
int main(){
scanf("%d", &n);
int fa;
for(int i = 2; i <= n; i++){
scanf("%d", &fa);
add_edge(i, fa); add_edge(fa, i);
}
for(int i = 1; i <= n; i++){scanf("%d", &k[i]);}
dfs(1, 0);
printf("%d\n", ans);
return 0;
}



京公网安备 11010502036488号