E. Split the Tree
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given a rooted tree on nn vertices, its root is the vertex number 11. The ii-th vertex contains a number wiwi. Split it into the minimum possible number of vertical paths in such a way that each path contains no more than LL vertices and the sum of integers wiwi on each path does not exceed SS. Each vertex should belong to exactly one path.
A vertical path is a sequence of vertices v1,v2,…,vkv1,v2,…,vk where vivi (i≥2i≥2) is the parent of vi−1vi−1.
Input
The first line contains three integers nn, LL, SS (1≤n≤1051≤n≤105, 1≤L≤1051≤L≤105, 1≤S≤10181≤S≤1018) — the number of vertices, the maximum number of vertices in one path and the maximum sum in one path.
The second line contains nn integers w1,w2,…,wnw1,w2,…,wn (1≤wi≤1091≤wi≤109) — the numbers in the vertices of the tree.
The third line contains n−1n−1 integers p2,…,pnp2,…,pn (1≤pi<i1≤pi<i), where pipi is the parent of the ii-th vertex in the tree.
Output
Output one number — the minimum number of vertical paths. If it is impossible to split the tree, output −1−1.
Examples
input
Copy
3 1 3 1 2 3 1 1
output
Copy
3
input
Copy
3 3 6 1 2 3 1 1
output
Copy
2
input
Copy
1 1 10000 10001
output
Copy
-1
Note
In the first sample the tree is split into {1}, {2}, {3}{1}, {2}, {3}.
In the second sample the tree is split into {1, 2}, {3}{1, 2}, {3} or {1, 3}, {2}{1, 3}, {2}.
In the third sample it is impossible to split the tree.
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mn = 1e5 + 10;
int f[mn][30], dep[mn], up[mn], top[mn];
ll w[mn], sum[mn][30];
int main()
{
int n, L; ll S; scanf("%d %d %lld", &n, &L, &S);
for (int i = 1; i <= n; i++)
{
scanf("%lld", &w[i]);
if (w[i] > S)
{
printf("-1\n");
return 0;
}
}
for (int i = 2; i <= n; i++) scanf("%d", &f[i][0]);
// 父节点编号小于子节点
dep[1] = 1;
for (int i = 1; i <= n; i++) // 相邻层之间
{
sum[i][0] = w[f[i][0]]; // 这个点之上节点的sum
dep[i] = dep[f[i][0]] + 1;
}
for (int j = 1; j <= 17; j++) /// 倍增
{
for (int i = 1; i <= n; i++)
{
int tf = f[i][j - 1];
f[i][j] = f[tf][j - 1];
sum[i][j] = sum[i][j - 1] + sum[tf][j - 1];
}
}
for (int i = 1; i <= n; i++)
{
int id = i, cnt = 1; ll tsum = w[i];
for (int j = 17; j >= 0; j--)
{ // 限制条件下点i能扩展到的最浅的点
if (f[id][j] != 0 && cnt + (1 << j) <= L && tsum + sum[id][j] <= S)
{
cnt += (1 << j), tsum += sum[id][j];
id = f[id][j]; // id 上跃
}
}
up[i] = id;
}
int ans = 0;
for (int i = n; i >= 1; i--)
{
if (!top[i]) // 新开一条链
ans++, top[i] = up[i];
int fa = f[i][0];
if (dep[top[i]] <= dep[fa] && (!top[fa] || dep[top[i]] < dep[top[fa]]))
top[fa] = top[i]; // 子节点创造的链覆盖的父节点们赋值了与子节点相同的可达最浅点
}
printf("%d\n", ans);
return 0;
}