#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
using namespace std;
struct BIT {
  vector<int> tree;
  BIT(int sz) { tree = vector<int>(sz + 1, 0); }
  void upd(int idx, int v) {
    for (idx++; idx < tree.size(); idx += idx & -idx) {
      tree[idx] += v;
    }
  }
  int query(int idx) {
    int res = 0;
    for (idx++; idx > 0; idx -= idx & -idx) {
      res += tree[idx];
    }
    return res;
  }
};
int n, l, ss[100000];
long long w, res;
bool solved[100000];
vector<pair<int, long long> > adj[100000];
void dfs1(int node, int par = -1) {
  ss[node] = 1;
  for (const pair<int, long long> edge : adj[node]) {
    int next = edge.first;
    if (next != par && !solved[next]) {
      dfs1(next, node);
      ss[node] += ss[next];
    }
  }
}
int find(int node) {
  dfs1(node);
  int par = -1;
  int total = ss[node];
  while (1) {
    bool breakout = true;
    for (const pair<int, long long> edge : adj[node]) {
      int next = edge.first;
      if (!solved[next] && next != par && ss[next] * 2 > total) {
        par = node;
        node = next;
        breakout = false;
        break;
      }
    }
    if (breakout) {
      break;
    }
  }
  return node;
}
vector<pair<int, long long> > combine(
    vector<vector<pair<int, long long> > >& vec) {
  vector<pair<int, long long> > res;
  for (const vector<pair<int, long long> > v : vec) {
    res.insert(res.end(), (v).begin(), (v).end());
  }
  return res;
}
long long count(const vector<pair<int, long long> >& _v) {
  vector<pair<int, long long> > v(_v);
  sort((v).begin(), (v).end(),
       [](pair<int, long long>& a, pair<int, long long>& b) -> bool {
         return make_pair(a.second, a.first) < make_pair(b.second, b.first);
       });
  vector<int> fVals;
  for (const pair<int, long long> p : v) {
    fVals.push_back(p.first);
  }
  sort((fVals).begin(), (fVals).end());
  long long ret = 0;
  int j = 0;
  BIT x(fVals.size());
  for (int i = (v.size()) - 1; i >= 0; i--) {
    while (j < i && v[j].second + v[i].second <= w) {
      x.upd(lower_bound((fVals).begin(), (fVals).end(), v[j++].first) -
                fVals.begin(),
            1);
    }
    if (j > i) {
      x.upd(lower_bound((fVals).begin(), (fVals).end(), v[--j].first) -
                fVals.begin(),
            -1);
    }
    ret += x.query(upper_bound((fVals).begin(), (fVals).end(), l - v[i].first) -
                   fVals.begin() - 1);
  }
  return ret;
}
void dfs2(int node, int par, vector<pair<int, long long> >& v, int depth = 0,
          long long depth2 = 0) {
  v.push_back(make_pair(depth, depth2));
  for (const pair<int, long long> edge : adj[node]) {
    int next = edge.first;
    if (next != par && !solved[next]) {
      dfs2(next, node, v, depth + 1, depth2 + edge.second);
    }
  }
}
void solve(int node) {
  node = find(node);
  vector<vector<pair<int, long long> > > vec;
  vec.push_back(vector<pair<int, long long> >(1, make_pair(0, 0)));
  for (const pair<int, long long> edge : adj[node]) {
    int next = edge.first;
    if (!solved[next]) {
      vec.push_back(vector<pair<int, long long> >());
      dfs2(next, node, vec.back(), 1, edge.second);
    }
  }
  for (vector<pair<int, long long> >& v : vec) {
    res -= count(v);
  }
  res += count(combine(vec));
  solved[node] = true;
  for (const pair<int, long long> edge : adj[node]) {
    int next = edge.first;
    if (!solved[next]) {
      solve(next);
    }
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> l >> w;
  for (int i = 0; i < (n - 1); i++) {
    int p;
    long long weight;
    cin >> p >> weight;
    p--;
    adj[p].push_back(make_pair(i + 1, weight));
    adj[i + 1].push_back(make_pair(p, weight));
  }
  solve(0);
  cout << res << "\n";
}
