← Home
```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)
}
```