#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;   }