#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
inline int getint() {
  int c;
  while (c = getchar(), (c < '0' || c > '9') && (c != '-') && (c != EOF))
    ;
  if (c == EOF) return -1;
  bool flag = (c == '-');
  if (flag) c = getchar();
  int x = 0;
  while (c >= '0' && c <= '9') {
    x = (x << 3) + x + x + c - '0';
    c = getchar();
  }
  return flag ? -x : x;
}
inline void writeln(long long x) {
  if (x < 0) {
    putchar('-');
    x = -x;
  }
  int len = 0, buf[20];
  while (x) {
    buf[len++] = x % 10;
    x /= 10;
  }
  if (!len) buf[len++] = 0;
  while (len--) putchar(buf[len] + '0');
  putchar('\n');
}
inline void write(long long x) {
  if (x < 0) {
    putchar('-');
    x = -x;
  }
  int len = 0, buf[20];
  while (x) {
    buf[len++] = x % 10;
    x /= 10;
  }
  if (!len) buf[len++] = 0;
  while (len--) putchar(buf[len] + '0');
}
const int N = 1e5 + 10;
const int M = N + N;
const int P = 20;
class graph {
 public:
  int head[N];
  int next[M];
  int node[M];
  int dist[M];
  int tot;
  void init() {
    tot = 0;
    memset(head, -1, sizeof(head));
    ;
  }
  void add(int x, int y, int z) {
    node[tot] = y;
    dist[tot] = z;
    next[tot] = head[x];
    head[x] = tot++;
  }
} g;
int n;
class DCT {
 public:
  int root;
  int head[N];
  int next[M];
  int node[M];
  int edge[M];
  int tot;
  bool del[N];
  int s[N];
  void init() {
    tot = 0;
    memset(head, -1, sizeof(head));
    ;
  }
  void add(int x, int y, int z) {
    node[tot] = y;
    next[tot] = head[x];
    edge[tot] = z;
    head[x] = tot++;
  }
  pair<int, int> findRoot(int x, int pre, int cnt, graph &g) {
    s[x] = 1;
    pair<int, int> res = make_pair(0x3f3f3f3f, x);
    int max_part = -0x3f3f3f3f;
    for (int i = g.head[(x)]; ~i; i = g.next[i]) {
      int y = g.node[i];
      if (del[y]) continue;
      if (y == pre) continue;
      res = min(findRoot(y, x, cnt, g), res);
      s[x] += s[y];
      max_part = max(max_part, s[y]);
    }
    max_part = max(max_part, cnt - s[x]);
    return res = min(res, make_pair(max_part, x));
  }
  int getSize(int x, int pre, graph &g) {
    int res = 1;
    for (int i = g.head[(x)]; ~i; i = g.next[i]) {
      int y = g.node[i];
      if (y == pre) continue;
      if (del[y]) continue;
      res += getSize(y, x, g);
    }
    return res;
  }
  void build(graph &g, int x) {
    del[x] = 1;
    for (int i = g.head[(x)]; ~i; i = g.next[i]) {
      int y = g.node[i];
      if (del[y]) continue;
      int ts = getSize(y, y, g);
      int tmp = findRoot(y, y, ts, g).second;
      s[tmp] = ts;
      add(x, tmp, i);
      build(g, tmp);
    }
  }
  void build(graph &g) {
    memset(del, 0, sizeof(del));
    ;
    root = findRoot(0, 0, n, g).second;
    s[root] = n;
    build(g, root);
  }
} dct;
class BIT {
 public:
  int data[N];
  int len;
  inline int lowerbit(int x) { return -x & x; }
  void init(int LEN) {
    len = LEN;
    fill(data, data + len, 0);
  }
  int sum(int x) {
    ++x;
    int res = 0;
    while (x > 0) {
      res += data[x - 1];
      x -= lowerbit(x);
    }
    return res;
  }
  void add(int x, int y) {
    ++x;
    while (x <= len) {
      data[x - 1] += y;
      x += lowerbit(x);
    }
  }
};
bool del[N];
int l, w;
BIT bit;
vector<pair<int, int> > update;
long long answer;
vector<pair<int, int> > all, sub;
void dfs(int pre, int x, int dist, int weight) {
  if (weight > w || dist > l) return;
  sub.push_back(make_pair(weight, dist));
  all.push_back(make_pair(weight, dist));
  for (int i = g.head[(x)]; ~i; i = g.next[i]) {
    if (g.node[i] == pre) continue;
    if (del[g.node[i]]) continue;
    dfs(x, g.node[i], dist + 1, weight + g.dist[i]);
  }
}
long long calc(vector<pair<int, int> > &num) {
  if (num.size() < 2) return 0;
  sort(num.begin(), num.end());
  int L = 0;
  int R = 1;
  bit.add(num[0].second, 1);
  bit.add(num[1].second, 1);
  while (R + 1 < num.size() && num[L].first + num[R + 1].first <= w) {
    ++R;
    bit.add(num[R].second, 1);
  }
  long long res = 0;
  while (L < R) {
    bit.add(num[L].second, -1);
    while (L < R && num[R].first + num[L].first > w) {
      bit.add(num[R].second, -1);
      --R;
    }
    res += bit.sum(min(bit.len - 1, l - num[L].second));
    ++L;
  }
  if (L == R) bit.add(num[L].second, -1);
  return res;
}
void work(int x) {
  del[x] = 1;
  all.clear();
  all.push_back(make_pair(0, 0));
  for (int i = dct.head[(x)]; ~i; i = dct.next[i]) {
    static int y = dct.node[i];
    sub.clear();
    dfs(g.node[dct.edge[i]], g.node[dct.edge[i]], 1, g.dist[dct.edge[i]]);
    answer -= calc(sub);
  }
  answer += calc(all);
  for (int i = dct.head[(x)]; ~i; i = dct.next[i]) {
    work(dct.node[i]);
  }
}
void solve() {
  all.reserve(n);
  sub.reserve(n);
  dct.build(g);
  memset(del, 0, sizeof(del));
  ;
  answer = 0;
  bit.init(n);
  work(dct.root);
}
void print() { writeln(answer); }
int main() {
  n = getint();
  l = getint();
  w = getint();
  g.init();
  dct.init();
  for (int i = (1); i < (n); ++i) {
    int x = i;
    int y = getint() - 1;
    int z = getint();
    g.add(x, y, z);
    g.add(y, x, z);
  }
  solve();
  print();
}
