黑白树

 

 

 

 题解:设k[ x ]为节点x以及它的子树中的点能往上走的最长距离,即 k[ x ] = max ( k[ x ] , k[ v ] -1 )  ,v是x的儿子,设f [ x ] 为选择了节点后还能往上走的距离, f[ x ] = max( f[ x ] , f[ v ] -1 ) , 当 f [ x ] = 0 时,答案加一,且 f [ x ] = k [ x ] 。

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=1e5+50;

int n,fa[maxn],k[maxn],f[maxn],ans;
int fir[maxn],nex[maxn<<1],to[maxn<<1],ecnt;

void add(int u,int v){
    nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;
}

void dfs(int x){
    for(int e=fir[x];e;e=nex[e]){
        int v=to[e];
        if(v==fa[x]) continue;
        dfs(v);
        k[x]=max(k[x],k[v]-1);
        f[x]=max(f[x],f[v]-1);
    }
    if(!f[x]){
        ans++;
        f[x]=k[x];
    }
}

template<typename T>void inline read(T &aa){
    ll ff=1;char cc=getchar();aa=0;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar();
    aa*=ff;
}

int main(){
    cin>>n;
    for(int i=2;i<=n;i++){
        read(fa[i]);
        add(fa[i],i);add(i,fa[i]);
    }
    for(int i=1;i<=n;i++) read(k[i]);
    dfs(1);
    cout<<ans<<endl;
    return 0;
}
View Code

 

posted @ 2021-07-21 16:29  rld  阅读(70)  评论(0编辑  收藏  举报