#include <bits/stdc++.h>
using namespace std;
vector<pair<int, int> > adj[100005];
int n, maxL, maxW;
int numChild[100005];
bool mark[100005];
long long ret = 0;
int center, total, queryCount, maxFound = 0;
vector<int> validPts[100005];
vector<int> Lexist;
vector<int> cordW[4 * 100005];
vector<int> fenwick[4 * 100005];
vector<int> tmpCord;
inline void refine(int idx) {
  cordW[idx].clear();
  sort(tmpCord.begin(), tmpCord.end());
  for (int i = 0; i < tmpCord.size(); i++)
    if (!i || tmpCord[i] > tmpCord[i - 1]) cordW[idx].push_back(tmpCord[i]);
  fenwick[idx].resize((int)cordW[idx].size() + 1);
  for (int i = 0; i < fenwick[idx].size(); i++) fenwick[idx][i] = 0;
}
inline void buildRangeTree(int i, int low, int high) {
  if (low == high) {
    tmpCord = validPts[low];
    refine(i);
    return;
  }
  int mid = (low + high) >> 1;
  buildRangeTree(2 * i, low, mid);
  buildRangeTree(2 * i + 1, mid + 1, high);
  tmpCord = cordW[2 * i];
  for (int j = 0; j < cordW[2 * i + 1].size(); j++)
    tmpCord.push_back(cordW[2 * i + 1][j]);
  refine(i);
}
inline void add(int i, int low, int high, int l, int w) {
  if (l < low || high < l) return;
  int alpha = 0, beta = cordW[i].size() - 1, pos = 0;
  while (alpha <= beta) {
    int gamma = (alpha + beta) >> 1;
    if (cordW[i][gamma] <= w) {
      pos = gamma;
      alpha = gamma + 1;
    } else
      beta = gamma - 1;
  }
  for (int x = pos + 1; x < fenwick[i].size(); x += x & -x) fenwick[i][x]++;
  if (low == high) return;
  int mid = (low + high) / 2;
  add(2 * i, low, mid, l, w);
  add(2 * i + 1, mid + 1, high, l, w);
}
inline void query(int i, int low, int high, int l, int w) {
  if (low > l) return;
  if (high <= l) {
    int alpha = 0, beta = cordW[i].size() - 1, pos = -1;
    while (alpha <= beta) {
      int gamma = (alpha + beta) >> 1;
      if (cordW[i][gamma] <= w) {
        pos = gamma;
        alpha = gamma + 1;
      } else
        beta = gamma - 1;
    }
    for (int x = pos + 1; x > 0; x -= x & -x) queryCount += fenwick[i][x];
    return;
  }
  int mid = (low + high) / 2;
  query(2 * i, low, mid, l, w);
  query(2 * i + 1, mid + 1, high, l, w);
}
inline void firstDFS(int u, int pre, int sgn) {
  numChild[u] = 1;
  for (int i = 0; i < adj[u].size(); i++) {
    int v = adj[u][i].first;
    if (v == pre || mark[v]) continue;
    firstDFS(v, u, sgn);
    numChild[u] += numChild[v];
  }
  if (sgn) {
    bool found = true;
    for (int i = 0; i < adj[u].size(); i++) {
      int v = adj[u][i].first;
      if (v == pre || mark[v]) continue;
      if (numChild[v] > total / 2) found = false;
    }
    if (total - numChild[u] > total / 2) found = false;
    if (found) center = u;
  }
}
inline int findCenter(int start, int pre) {
  center = -1;
  firstDFS(start, pre, 0);
  total = numChild[start];
  firstDFS(start, pre, 1);
  return center;
}
inline void secondDFS(int u, int par, int l, int w) {
  if (l > maxL || w > maxW) return;
  validPts[l].push_back(w);
  maxFound = max(maxFound, l);
  Lexist.push_back(l);
  for (int i = 0; i < adj[u].size(); i++) {
    int v = adj[u][i].first;
    if (v == par || mark[v]) continue;
    secondDFS(v, u, l + 1, w + adj[u][i].second);
  }
}
inline void thirdDFS(int u, int par, int l, int w, int flag) {
  if (l > maxL || w > maxW) return;
  if (!flag && par >= 0) {
    queryCount = 0;
    query(1, 0, maxFound, maxL - l, maxW - w);
    ret += queryCount;
  } else {
    add(1, 0, maxFound, l, w);
  }
  for (int i = 0; i < adj[u].size(); i++) {
    int v = adj[u][i].first;
    if (v == par || mark[v]) continue;
    thirdDFS(v, u, l + 1, w + adj[u][i].second, flag);
    if (par < 0 && flag == 0) thirdDFS(v, u, l + 1, w + adj[u][i].second, 1);
  }
}
inline void booking(int u) {
  mark[u] = true;
  for (int i = 0; i < Lexist.size(); i++) validPts[Lexist[i]].clear();
  Lexist.clear();
  maxFound = 0;
  secondDFS(u, -1, 0, 0);
  buildRangeTree(1, 0, maxFound);
  thirdDFS(u, -1, 0, 0, 0);
}
inline void recurse(int start, int pre) {
  int u = findCenter(start, pre);
  booking(u);
  for (int i = 0; i < adj[u].size(); i++)
    if (!mark[adj[u][i].first]) recurse(adj[u][i].first, u);
}
int main() {
  scanf("%d %d %d", &n, &maxL, &maxW);
  for (int i = 2; i <= n; i++) {
    int p, w;
    scanf("%d %d", &p, &w);
    adj[p].push_back(make_pair(i, w));
    adj[i].push_back(make_pair(p, w));
  }
  recurse(1, -1);
  cout << ret << endl;
}
