#include <bits/stdc++.h>
using namespace std;
const int Maxn = int(1e5);
inline int read() {
  int x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return x * f;
}
struct Node {
  int to, nxt, w;
} Edge[Maxn * 2 + 5];
int tot, Head[Maxn + 5];
inline void Addedge(int x, int y, int z) {
  Edge[++tot] = (Node){y, Head[x], z};
  Head[x] = tot;
}
long long ans;
int n, l, w, rt, sum;
int siz[Maxn + 5], maxs[Maxn + 5], vis[Maxn + 5];
int dis1[Maxn + 5], dis2[Maxn + 5], cur, allcur;
struct Point {
  int a, b, c;
} tmp[Maxn + 5], all[Maxn + 5];
inline int cmp1(Point x, Point y) { return x.a < y.a; }
inline int cmp2(Point x, Point y) { return x.a > y.a; }
int t[Maxn + 5], top;
inline void Add(int x, int y) {
  while (x <= l) t[x] += y, x += (x & -x);
}
inline int Query(int x) {
  int res = 0;
  while (x > 0) res += t[x], x -= (x & -x);
  return res;
}
inline void dfs1(int x, int f) {
  siz[x] = 1, maxs[x] = 0;
  for (register int i = Head[x]; i; i = Edge[i].nxt) {
    int y = Edge[i].to;
    if (y == f || vis[y]) continue;
    dfs1(y, x);
    siz[x] += siz[y];
    maxs[x] = max(maxs[x], siz[y]);
  }
  maxs[x] = max(maxs[x], sum - siz[x]);
  rt = maxs[x] < maxs[rt] ? x : rt;
}
inline void dfs2(int x, int f, int grand) {
  tmp[++cur] = (Point){dis1[x], dis2[x], grand};
  for (register int i = Head[x]; i; i = Edge[i].nxt) {
    int y = Edge[i].to;
    if (y == f || vis[y]) continue;
    dis1[y] = dis1[x] + Edge[i].w;
    dis2[y] = dis2[x] + 1;
    dfs2(y, x, grand);
  }
}
inline void Count(int x) {
  int it = 1;
  allcur = 0;
  for (register int i = Head[x]; i; i = Edge[i].nxt) {
    int y = Edge[i].to;
    if (vis[y]) continue;
    dis1[y] = Edge[i].w, dis2[y] = 1;
    cur = 0, dfs2(y, x, y);
    for (register int j = 1; j <= cur; ++j)
      if (tmp[j].a <= w) all[++allcur] = tmp[j];
  }
  sort(all + 1, all + allcur + 1, cmp1);
  for (register int i = Head[x]; i; i = Edge[i].nxt) {
    int y = Edge[i].to;
    if (vis[y]) continue;
    dis1[y] = Edge[i].w, dis2[y] = 1;
    it = 1, cur = 0, dfs2(y, x, y);
    sort(tmp + 1, tmp + cur + 1, cmp2);
    for (register int j = 1; j <= cur; ++j) {
      while (it <= allcur && tmp[j].a + all[it].a <= w) {
        if (all[it].c < y) Add(all[it].b, 1);
        it++;
      }
      if (tmp[j].a <= w && tmp[j].b <= l) ans++;
      if (tmp[j].b < l) ans += Query(l - tmp[j].b);
    }
    for (register int j = 1; j < it; ++j)
      if (all[j].c < y) Add(all[j].b, -1);
  }
}
inline void Divide(int x) {
  vis[x] = 1;
  Count(x);
  for (register int i = Head[x]; i; i = Edge[i].nxt) {
    int y = Edge[i].to;
    if (vis[y]) continue;
    rt = 0, maxs[0] = sum = siz[y];
    dfs1(y, 0), dfs1(rt, 0);
    Divide(rt);
  }
}
int main() {
  n = read(), l = read(), w = read();
  for (register int i = 1; i < n; ++i) {
    int a = read(), b = read();
    Addedge(i + 1, a, b), Addedge(a, i + 1, b);
  }
  maxs[0] = sum = n;
  dfs1(1, 0), dfs1(rt, 0);
  Divide(rt);
  printf("%I64d", ans);
  return 0;
}
