You are given a rooted tree on n vertices, its root is the vertex number 1. The i-th vertex contains a number w_i. Split it into the minimum possible number of vertical paths in such a way that each path contains no more than L vertices and the sum of integers w_i on each path does not exceed S. Each vertex should belong to exactly one path.

A vertical path is a sequence of vertices v_1, v_2, …, v_k where v_i (i ≥ 2) is the parent of v_{i - 1}.

Input

The first line contains three integers n, L, S (1 ≤ n ≤ 10^5, 1 ≤ L ≤ 10^5, 1 ≤ S ≤ 10^{18}) — the number of vertices, the maximum number of vertices in one path and the maximum sum in one path.

The second line contains n integers w_1, w_2, …, w_n (1 ≤ w_i ≤ 10^9) — the numbers in the vertices of the tree.

The third line contains n - 1 integers p_2, …, p_n (1 ≤ p_i < i), where p_i is the parent of the i-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.

Examples

Input

3 1 3
1 2 3
1 1


Output

3

Input

3 3 6
1 2 3
1 1


Output

2

Input

1 1 10000
10001


Output

-1

Note

In the first sample the tree is split into \{1\},\ \{2\},\ \{3\}.

In the second sample the tree is split into \{1,\ 2\},\ \{3\} or \{1,\ 3\},\ \{2\}.

In the third sample it is impossible to split the tree.
#include <bits/stdc++.h>
using namespace std;
template <class T, class T2>
inline int chkmax(T &x, const T2 &y) {
  return x < y ? x = y, 1 : 0;
}
template <class T, class T2>
inline int chkmin(T &x, const T2 &y) {
  return x > y ? x = y, 1 : 0;
}
const int MAXN = (1 << 17);
const int64_t inf = (int64_t)1e18 + 42;
struct node {
  pair<int64_t, int> mn, mx;
  int64_t lazy;
  node() {
    mx = {-inf, -1};
    mn = {inf, -1};
    lazy = 0;
  }
  node(int64_t val, int pos) {
    mn = mx = {val, pos};
    lazy = 0;
  }
};
node temp, broken;
node merge(node l, node r) {
  temp.mn = min(l.mn, r.mn);
  temp.mx = max(l.mx, r.mx);
  temp.lazy = 0;
  return temp;
}
struct segment_tree {
  node tr[4 * MAXN];
  void push(int l, int r, int idx) {
    if (tr[idx].lazy) {
      tr[idx].mn.first += tr[idx].lazy;
      tr[idx].mx.first += tr[idx].lazy;
      if (l != r) {
        tr[2 * idx + 1].lazy += tr[idx].lazy;
        tr[2 * idx + 2].lazy += tr[idx].lazy;
      }
      tr[idx].lazy = 0;
    }
  }
  void init(int l, int r, int idx) {
    if (l == r) {
      tr[idx] = node(0, l);
      return;
    }
    int mid = (l + r) >> 1;
    init(l, mid, 2 * idx + 1);
    init(mid + 1, r, 2 * idx + 2);
    tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
  }
  void update(int qL, int qR, int64_t val, int l, int r, int idx) {
    push(l, r, idx);
    if (qL > r || l > qR) return;
    if (qL <= l && r <= qR) {
      tr[idx].lazy += val;
      push(l, r, idx);
      return;
    }
    int mid = (l + r) >> 1;
    update(qL, qR, val, l, mid, 2 * idx + 1);
    update(qL, qR, val, mid + 1, r, 2 * idx + 2);
    tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
  }
  node query(int qL, int qR, int l, int r, int idx) {
    push(l, r, idx);
    if (l > qR || r < qL) return broken;
    if (qL <= l && r <= qR) return tr[idx];
    int mid = (l + r) >> 1;
    return merge(query(qL, qR, l, mid, 2 * idx + 1),
                 query(qL, qR, mid + 1, r, 2 * idx + 2));
  }
};
int n;
int64_t L, S, w[MAXN];
vector<int> adj[MAXN];
void read() {
  cin >> n >> L >> S;
  for (int i = 1; i <= n; i++) {
    cin >> w[i];
    if (w[i] > S) {
      cout << -1 << '\n';
      exit(0);
    }
  }
  for (int i = 2; i <= n; i++) {
    int x;
    cin >> x;
    adj[x].push_back(i);
  }
}
int dp[MAXN];
int st[MAXN], en[MAXN], dfs_time;
segment_tree t_l, t_dp, t_w;
void pre_dfs(int u) {
  st[u] = ++dfs_time;
  for (int v : adj[u]) pre_dfs(v);
  en[u] = dfs_time;
}
void dfs(int u) {
  dp[u] = 1;
  for (int v : adj[u]) {
    dfs(v);
    dp[u] += dp[v];
  }
  t_w.update(st[u], en[u], w[u], 1, n, 0);
  t_l.update(st[u], en[u], 1, 1, n, 0);
  while (true) {
    auto it = t_w.tr[0].mx;
    if (it.first <= S) break;
    int pos = it.second;
    t_w.update(pos, pos, -2 * inf, 1, n, 0);
    t_dp.update(pos, pos, inf, 1, n, 0);
    t_l.update(pos, pos, -inf, 1, n, 0);
  }
  while (true) {
    auto it = t_l.tr[0].mx;
    if (it.first <= L) break;
    int pos = it.second;
    t_w.update(pos, pos, -2 * inf, 1, n, 0);
    t_dp.update(pos, pos, inf, 1, n, 0);
    t_l.update(pos, pos, -inf, 1, n, 0);
  }
  int64_t sum = dp[u] - 1;
  for (int v : adj[u]) {
    t_dp.update(st[v], en[v], sum - dp[v], 1, n, 0);
    chkmin(dp[u], t_dp.query(st[v], en[v], 1, n, 0).mn.first + 1);
  }
  t_dp.update(st[u], st[u], sum, 1, n, 0);
}
void solve() {
  pre_dfs(1);
  t_l.init(1, n, 0);
  t_w.init(1, n, 0);
  t_dp.init(1, n, 0);
  dfs(1);
  cout << dp[1] << '\n';
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  read();
  solve();
  return 0;
}
