```go
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
)
var head []int
var to []int
var weight []int
var next []int
var edgeCount int
func addEdge(u, v, w int) {
to[edgeCount] = v
weight[edgeCount] = w
next[edgeCount] = head[u]
head[u] = edgeCount
edgeCount++
}
var deleted []bool
var sz []int
var pairBuf []Pair
type Pair struct {
W int
L int
}
var max_W, max_L int
var ans int64
var bit []int
var qHead []int
var qNext []int
var qVal []int
func add(idx int, val int) {
idx++
for ; idx < len(bit); idx += idx & -idx {
bit[idx] += val
}
}
func query(idx int) int {
idx++
sum := 0
for ; idx > 0; idx -= idx & -idx {
sum += bit[idx]
}
return sum
}
func countPairs(A []Pair, w, maxL int) int64 {
if len(A) == 0 {
return 0
}
sort.Slice(A, func(i, j int) bool {
return A[i].W < A[j].W
})
for i := 0; i < len(A); i++ {
qHead[i] = -1
}
qCount := 0
var selfPairs int64 = 0
for j := 0; j < len(A); j++ {
if A[j].W*2 <= w && A[j].L*2 <= maxL {
selfPairs++
}
target := w - A[j].W
if target < 0 {
continue
}
left, right := 0, len(A)-1
ansIdx := -1
for left <= right {
mid := (left + right) / 2
if A[mid].W <= target {
ansIdx = mid
left = mid + 1
} else {
right = mid - 1
}
}
R_j := ansIdx
if R_j >= 0 {
L_req := maxL - A[j].L
if L_req >= 0 {
qNext[qCount] = qHead[R_j]
qVal[qCount] = L_req
qHead[R_j] = qCount
qCount++
}
}
}
var totalPairs int64 = 0
for i := 0; i < len(A); i++ {
if A[i].L <= maxL {
add(A[i].L, 1)
}
for e := qHead[i]; e != -1; e = qNext[e] {
val := qVal[e]
if val > maxL {
val = maxL
}
totalPairs += int64(query(val))
}
}
for i := 0; i < len(A); i++ {
if A[i].L <= maxL {
add(A[i].L, -1)
}
}
return (totalPairs - selfPairs) / 2
}
func getSz(u, p int) {
sz[u] = 1
for e := head[u]; e != -1; e = next[e] {
v := to[e]
if v != p && !deleted[v] {
getSz(v, u)
sz[u] += sz[v]
}
}
}
func getCentroid(u, p, total int) int {
for e := head[u]; e != -1; e = next[e] {
v := to[e]
if v != p && !deleted[v] && sz[v]*2 > total {
return getCentroid(v, u, total)
}
}
return u
}
func getNodes(u, p, w, l int) {
pairBuf = append(pairBuf, Pair{w, l})
for e := head[u]; e != -1; e = next[e] {
v := to[e]
if v != p && !deleted[v] {
getNodes(v, u, w+weight[e], l+1)
}
}
}
func solve(u int) {
getSz(u, -1)
centroid := getCentroid(u, -1, sz[u])
compStart := len(pairBuf)
pairBuf = append(pairBuf, Pair{0, 0})
for e := head[centroid]; e != -1; e = next[e] {
v := to[e]
if !deleted[v] {
branchStart := len(pairBuf)
getNodes(v, centroid, weight[e], 1)
branchEnd := len(pairBuf)
ans -= countPairs(pairBuf[branchStart:branchEnd], max_W, max_L)
}
}
compEnd := len(pairBuf)
ans += countPairs(pairBuf[compStart:compEnd], max_W, max_L)
pairBuf = pairBuf[:compStart]
deleted[centroid] = true
for e := head[centroid]; e != -1; e = next[e] {
v := to[e]
if !deleted[v] {
solve(v)
}
}
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
const maxCapacity = 1024 * 1024
buf := make([]byte, maxCapacity)
scanner.Buffer(buf, maxCapacity)
scanner.Split(bufio.ScanWords)
nextInt := func() int {
scanner.Scan()
v, _ := strconv.Atoi(scanner.Text())
return v
}
if !scanner.Scan() {
return
}
n, _ := strconv.Atoi(scanner.Text())
max_L = nextInt()
max_W = nextInt()
head = make([]int, n+1)
for i := range head {
head[i] = -1
}
to = make([]int, 2*n)
weight = make([]int, 2*n)
next = make([]int, 2*n)
for i := 1; i < n; i++ {
p := nextInt()
wt := nextInt()
addEdge(i+1, p, wt)
addEdge(p, i+1, wt)
}
bit = make([]int, n+5)
qHead = make([]int, n+5)
qNext = make([]int, n+5)
qVal = make([]int, n+5)
deleted = make([]bool, n+1)
sz = make([]int, n+1)
pairBuf = make([]Pair, 0, n+1)
solve(1)
fmt.Println(ans)
}
```