Alyona and the Tree CodeForces - 682C DFS
题目大意:有一棵树,节点有权值,边也有权值,问满足dist(v, u) >a[u]的节点有多少个,dist(v, u)是说u,v两个节点之间的距离,a[u]是说这个节点的权值。需要注意的事情是这棵树有根1。
题目分析:一开始的时候,有个疑问是对于一棵子树,如果它的根去掉了,那么他的子树是往上接还是直接去掉,很迷,后来仔细看了看样例,发现是直接去掉了。
这题一个很重要的点,就是当dfs的时候,把路径值累加起来,但是有负数,这样就会出现加到一个节点,它本身比a[u]大,但是加上之前的负数就变小了,这样我们就错加了。所以当我们累加值sum<0时,把它变为0就可以了。
样例:
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
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
struct node {
int v;
ll w;
};
int data[maxn], ans;
vector<node> Edge[maxn];
void dfs(int root, int pre, ll sum) {
ans++;
// printf("!!!%d %d %d\n", root, pre, ans);
for(int i = 0; i < Edge[root].size(); i++) {
int to = Edge[root][i].v;
if(to != pre) {
if(sum < 0) sum = 0;
if(sum + Edge[root][i].w <= data[to])
dfs(to, root, sum + Edge[root][i].w);
}
}
}
int main()
{
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%d", &data[i + 1]);
}
for(int i = 1; i < n; i++) {
int v;
ll w;
scanf("%d %lld", &v, &w);
Edge[v].push_back((node) {i + 1, w});
Edge[i + 1].push_back((node) {v, w});
}
ans = 0;
dfs(1, -1, 0);
printf("%d\n", n - ans);
}