Solution
由题意可知叶子节点必定要染色。对于其他节点:
- 若此节点的已经染色的子节点中,可以将它覆盖,那么不需要染色,并借助这个点能覆盖的范围更新最大范围。
- 若此节点的已经染色的子节点中,不能将它覆盖,那么需要将其子节点中范围最大的点染色,并更新最大范围。
可以发现这是一个由子节点向父节点更新的过程,所以可以使用 。每次贪心地更新能覆盖的最大距离,不能覆盖就进行染色。
时间复杂度: 。
Code
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1e5+10;
struct edge{
int t;
int v;
}e[maxn<<1];
int ans,tot,n,k[maxn],hd[maxn];
void add(int x,int y){
tot++;
e[tot].t=hd[x];
e[tot].v=y;
hd[x]=tot;
}
int dfs(int u,int fa){
int sum=0;
for(int i=hd[u];i!=0;i=e[i].t)
if(e[i].v!=fa)
sum=max(sum,dfs(e[i].v,u));
if(!sum){
ans++;
return k[u]-1;
}
k[fa]=max(k[fa],k[u]-1);//将所有子节点能覆盖的最大范围更新到父节点上,方便染色后返回
return sum-1;
}
int main(){
ios::sync_with_stdio(false);
cin>>n;
int x;
for(int i=2;i<=n;i++){
cin>>x;
add(x,i);
add(i,x);
}
for(int i=1;i<=n;i++)
cin>>k[i];
dfs(1,0);
cout<<ans;
return 0;
} 
京公网安备 11010502036488号