传送门
题意
在一棵树上存在这样一个节点
,满足
存在
的子树中,若
那么
点是
的233你只能从叶子节点开始删除点,问你最少删除多少个点,可以使得这个树里面没有不开心的点
题解
wow发现这道题好6啊!(来自蒟蒻的感慨….
来好好分析一下这道题 如果我们找到了一个点是
的 那么我们就要把他整棵子树给删掉
那么我们的问题就转换成了找
的点即它子树的大小了 继续思考下去 发现
点并不好求
因为边权有可能是负的 但点权肯定是大于等于1的
那么我们就转换成求不需要删除的点
我们一路
下去的时候
就记录下每个点到根的距离(注意啦注意啦(当
的时候距离要和
取个
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=1e5+1;
struct data{
int next,to,w;
}a[N<<1];
int head[N];
LL v[N];
int ans=0,cnt=0;
void add(int x,int y,int w){
a[++cnt].to=x,a[cnt].next=head[y],a[cnt].w=w,head[y]=cnt;
a[++cnt].to=y,a[cnt].next=head[x],a[cnt].w=w,head[x]=cnt;
}
int dfs(int u,int fa,LL dis){
if(dis>v[u]) return 0;
int res=1;
for(int i=head[u];i!=-1;i=a[i].next){
if(a[i].to!=fa){
res+=dfs(a[i].to,u,max(dis+a[i].w,0LL)); //
}
}
return res;
}
int main(){
int n,son,w;scanf("%d",&n);
memset(head,-1,sizeof(head));
for(int i=1;i<=n;++i) scanf("%lld",&v[i]);
for(int i=1;i<n;++i){
scanf("%d%d",&son,&w);
add(i+1,son,w);
}
ans=dfs(1,0,0);
printf("%d",n-ans);
return 0;
}