原题:点击打开链接
给你一棵树,1为该树的根只要有任意一条到i的路径是大于num[i],就要将该点和该点子树删掉。
从1开始搜索路径,取一到任意点的最大路径,若最大路径大于num[i],则可以将该点与子树删除。当路径为负数时要清零。
#include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <vector> using namespace std; const int maxn=1e5+5; vector<int> s[maxn],w[maxn],c[maxn]; int n,sum,num[maxn],vis[maxn],viss[maxn],k,flag; long long w1[maxn],wmax[maxn]; void dfs2(int u) { for(int i=0;i<s[u].size();i++) { if(!vis[s[u][i]]) vis[s[u][i]]=1; dfs2(s[u][i]); } } void dfs1(int u) { for(int i=0;i<s[u].size();i++) { int v=s[u][i]; if(vis[v]) continue; w1[v]=w1[u]+w[u][i]; wmax[v]=max(wmax[v],w1[v]); if(w1[v]<0) w1[v]=0; if(wmax[v]>num[v]){ vis[v]=1; dfs2(v); } if(!vis[v]) dfs1(v); } } int main() { int n; while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++) { int a; scanf("%d",&a); num[i]=a; } for(int i=1;i<=n-1;i++) { int a,b; scanf("%d%d",&a,&b); s[a].push_back(i+1); w[a].push_back(b); // c[a].push_back(i+1); } sum=0; memset(vis,0,sizeof(vis)); memset(w1,0,sizeof(w1)); memset(wmax,0,sizeof(wmax)); dfs1(1); for(int i=2;i<=n;i++) if(vis[i]) sum++; printf("%d\n",sum); } }