1 second
256 megabytes
standard input
standard output
Alyona decided to go on a diet and went to the forest to get some apples. There she unexpectedly found a magic rooted tree with root in the vertex 1, every vertex and every edge of which has a number written on.
The girl noticed that some of the tree's vertices are sad, so she decided to play with them. Let's call vertex v sad if there is a vertex u in subtree of vertex v such that dist(v, u) > au, where au is the number written on vertex u, dist(v, u) is the sum of the numbers written on the edges on the path from v to u.
Leaves of a tree are vertices connected to a single vertex by a single edge, but the root of a tree is a leaf if and only if the tree consists of a single vertex — root.
Thus Alyona decided to remove some of tree leaves until there will be no any sad vertex left in the tree. What is the minimum number of leaves Alyona needs to remove?
In the first line of the input integer n (1 ≤ n ≤ 105) is given — the number of vertices in the tree.
In the second line the sequence of n integers a1, a2, ..., an (1 ≤ ai ≤ 109) is given, where ai is the number written on vertex i.
The next n - 1 lines describe tree edges: ith of them consists of two integers pi and ci (1 ≤ pi ≤ n, - 109 ≤ ci ≤ 109), meaning that there is an edge connecting vertices i + 1 and pi with number ci written on it.
Print the only integer — the minimum number of leaves Alyona needs to remove such that there will be no any sad vertex left in the tree.
9
88 22 83 14 95 91 98 53 11
3 24
7 -8
1 67
1 64
9 65
5 12
6 -80
3 8
5
The following image represents possible process of removing leaves from the tree:
比较有意思的一道题,刚开始题意理解错了,以为一定是从1开始,后来发现是最远可以是1,最近就是从父节点开始,那么边权和就变成了Max{0(舍弃之前的边从最近的父节点开始),sumpre(加上之前的边)}。然后再发现这道题也叫什么树形DP,反正也就听过的样子。一开始写BFS只能过两组数据,因为无法知道到底最合适起点在哪里。因此要用动态的思想,一开是BFS去计算减掉多少枝叶,看了别人博客才明白用逆向思维,因为你减掉的枝叶可能会重复,也可能这个枝叶根本不是从最优开始点开始计算的,也就无法得知这个节点到底算不算sad……题意是若中间出现了一个sad,那么这个sad点的后代点全部都要摘掉,因此去计算从1开始向外拓展的可保留点比较好,那显然就是DFS了。还有由于是无向图,边数要乘以2,两次RE
代码:
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x) memset(x,0,sizeof(x))
#define MMINF(x) memset(x,INF,sizeof(x))
typedef long long LL;
const double PI=acos(-1.0);
const int N=200010;
int r;
struct info
{
int to;
int pre;
int d;
}E[N];
int head[N],cnt,w[N],vis[N];
void add(int s,int t,int dx)
{
E[cnt].to=t;
E[cnt].pre=head[s];
E[cnt].d=dx;
head[s]=cnt++;
}
void init()
{
memset(head,-1,sizeof(head));
MM(w);MM(vis);
cnt=0;
r=0;
}
void dfs(const int &now,const int &pre,const LL &nowval)
{
if(w[now]<nowval||vis[now])
return ;
vis[now]=1;
r++;
for (int i=head[now]; i!=-1; i=E[i].pre)
{
int v=E[i].to;
dfs(v,now,max<LL>((LL)0,((LL)nowval+(LL)E[i].d)));
}
}
int main(void)
{
int n,i,j,x,y;
while (~scanf("%d",&n))
{
init();
for (i=1; i<=n; i++)
{
scanf("%d",&w[i]);
}
for (i=1; i<=n-1; i++)
{
scanf("%d%d",&x,&y);
add(i+1,x,y);
add(x,i+1,y);
}
dfs(1,1,(LL)0);
printf("%d\n",n-r);
}
return 0;
}