#include <bits/stdc++.h>
#pragma GCC optimize("03")
using namespace std;
struct Node {
  int x;
  Node *lc, *rc;
  Node() {}
  Node(int x) : lc(nullptr), rc(nullptr), x(x) {}
  Node(Node* lc, Node* rc) : lc(lc), rc(rc), x(lc->x + rc->x) {}
} buf[10000000];
int bsz;
Node* build(int l, int r) {
  if (l == r) {
    buf[bsz] = Node(0);
    return &buf[bsz++];
  } else {
    int m = l + r >> 1;
    buf[bsz] = Node(build(l, m), build(m + 1, r));
    return &buf[bsz++];
  }
}
Node* update(Node* p, int l, int r, int i, int x) {
  if (l == r) {
    buf[bsz] = Node(p->x + x);
    return &buf[bsz++];
  } else {
    int m = l + r >> 1;
    if (i <= m) {
      buf[bsz] = Node(update(p->lc, l, m, i, x), p->rc);
      return &buf[bsz++];
    } else {
      buf[bsz] = Node(p->lc, update(p->rc, m + 1, r, i, x));
      return &buf[bsz++];
    }
  }
}
int query(Node* p, int l, int r, int ql, int qr) {
  if (ql <= l && r <= qr) {
    return p->x;
  } else {
    int m = l + r >> 1;
    if (qr <= m) {
      return query(p->lc, l, m, ql, qr);
    } else if (ql > m) {
      return query(p->rc, m + 1, r, ql, qr);
    } else {
      return query(p->lc, l, m, ql, qr) + query(p->rc, m + 1, r, ql, qr);
    }
  }
}
struct Graph {
  int first, last, n;
  vector<vector<pair<int, int>>> adj;
  Graph(int n, bool b) : first(b), last(n + b), n(n), adj(last) {}
  void addEdge(int u, int v, int w) {
    adj[u].emplace_back(w, v);
    adj[v].emplace_back(w, u);
  }
  void addArc(int u, int v, int w) { adj[u].emplace_back(w, v); }
};
template <typename T>
struct CoordinateCompression {
  vector<T> o;
  void push(const T& x) { o.push_back(x); }
  int build() {
    sort(o.begin(), o.end());
    o.erase(unique(o.begin(), o.end()), o.end());
    return o.size();
  }
  int operator()(const T& x) {
    auto it = upper_bound(o.begin(), o.end(), x);
    return it - o.begin();
  }
  T& operator[](int i) { return o[i]; }
};
int H, D;
struct CentroidDecomposition {
  Graph g;
  vector<int> sz;
  vector<bool> cut;
  long long ans;
  CentroidDecomposition(Graph&& g) : g(g), sz(g.last), cut(g.last), ans(0) {
    solve(g.first, g.first, 0);
  }
  void sizes(int u, int par) {
    sz[u] = 1;
    for (auto [w, v] : g.adj[u]) {
      if (v == par || cut[v]) continue;
      sizes(v, u);
      sz[u] += sz[v];
    }
  }
  int find(int u, int par, int cnt) {
    for (auto [w, v] : g.adj[u]) {
      if (v == par || cut[v]) continue;
      if (sz[v] << 1 > cnt) return find(v, u, cnt);
    }
    return u;
  }
  template <class F>
  void halfPaths(int u, int par, int h, long long d, const F& get) {
    get(u, h, d);
    for (auto [w, v] : g.adj[u]) {
      if (v == par || cut[v]) continue;
      halfPaths(v, u, h + 1, d + w, get);
    }
  }
  void solve(int c, int par, int h) {
    sizes(c, par);
    c = find(c, par, sz[c]);
    cut[c] = true;
    int deep = 0;
    CoordinateCompression<long long> cc;
    halfPaths(c, c, 0, 0, [&](int u, int h, long long d) {
      deep = max(deep, h);
      cc.push(d);
    });
    int z = cc.build();
    vector<vector<long long>> upd(deep + 1);
    halfPaths(c, c, 0, 0,
              [&](int u, int h, long long d) { upd[h].push_back(d); });
    vector<Node*> version(deep + 1);
    version[0] = update(build(0, z - 1), 0, z - 1, 0, 1);
    for (int h = 1; h <= deep; h++) {
      version[h] = version[h - 1];
      for (long long d : upd[h]) {
        int i = cc(d);
        version[h] = update(version[h], 0, z - 1, i - 1, 1);
      }
    }
    halfPaths(c, c, 0, 0, [&](int u, int h, long long d) {
      if (h > H) return;
      int i = cc(D - d);
      if (i == 0) return;
      ans += query(version[min(H - h, deep)], 0, z - 1, 0, i - 1);
    });
    for (auto [w, r] : g.adj[c]) {
      bsz = 0;
      if (!cut[r]) {
        fill(upd.begin(), upd.end(), vector<long long>());
        cc.o.clear();
        halfPaths(r, c, 1, w, [&](int u, int h, long long d) {
          cc.push(d);
          upd[h].push_back(d);
        });
        z = cc.build();
        version[0] = build(0, z - 1);
        for (int h = 1; h <= deep; h++) {
          version[h] = version[h - 1];
          for (long long d : upd[h]) {
            version[h] = update(version[h], 0, z - 1, cc(d) - 1, 1);
          }
        }
        halfPaths(r, c, 1, w, [&](int u, int h, long long d) {
          if (h > H) return;
          int i = cc(D - d);
          if (i == 0) return;
          ans -= query(version[min(H - h, deep)], 0, z - 1, 0, i - 1);
        });
      }
    }
    for (auto [w, r] : g.adj[c]) {
      if (!cut[r]) solve(r, c, h + 1);
    }
  }
};
int main() {
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  int n;
  cin >> n >> H >> D;
  Graph g(n, 1);
  for (int u = 2; u <= n; u++) {
    int v, w;
    cin >> v >> w;
    g.addEdge(u, v, w);
  }
  CentroidDecomposition cd(move(g));
  cout << (cd.ans - n >> 1) << '\n';
}
