← Home
```go
package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
)

type Edge struct {
	to, w int
}

type Path struct {
	L, W int
}

var (
	adj          [][]Edge
	deleted      []bool
	sz           []int
	ans          int64
	l, w         int
	currentPaths []Path
	U            []int
	bit          []int
	dfs          func(v, p, depth, weight int)
)

func init() {
	dfs = func(v, p, depth, weight int) {
		if depth > l || weight > w {
			return
		}
		currentPaths = append(currentPaths, Path{depth, weight})
		for _, edge := range adj[v] {
			if edge.to != p && !deleted[edge.to] {
				dfs(edge.to, v, depth+1, weight+edge.w)
			}
		}
	}
}

func getSizes(u, p int) int {
	sz[u] = 1
	for _, e := range adj[u] {
		if e.to != p && !deleted[e.to] {
			sz[u] += getSizes(e.to, u)
		}
	}
	return sz[u]
}

func getCentroid(u, p, total int) int {
	for _, e := range adj[u] {
		if e.to != p && !deleted[e.to] && sz[e.to] > total/2 {
			return getCentroid(e.to, u, total)
		}
	}
	return u
}

func countPaths(paths []Path, l, w int) int64 {
	n := len(paths)
	if n <= 1 {
		return 0
	}
	sort.Slice(paths, func(i, j int) bool {
		return paths[i].L < paths[j].L
	})

	if cap(U) < n {
		U = make([]int, n)
	}
	U = U[:n]
	for i := 0; i < n; i++ {
		U[i] = paths[i].W
	}
	sort.Ints(U)

	unique := 0
	for i := 0; i < n; i++ {
		if i == 0 || U[i] != U[i-1] {
			U[unique] = U[i]
			unique++
		}
	}
	U = U[:unique]

	getIdx := func(val int) int {
		left, right := 0, unique
		for left < right {
			mid := int(uint(left+right) >> 1)
			if U[mid] <= val {
				left = mid + 1
			} else {
				right = mid
			}
		}
		return left
	}

	if cap(bit) < unique+1 {
		bit = make([]int, unique+1)
	}
	bit = bit[:unique+1]
	for i := 0; i <= unique; i++ {
		bit[i] = 0
	}

	add := func(idx, val int) {
		for ; idx <= unique; idx += idx & -idx {
			bit[idx] += val
		}
	}
	query := func(idx int) int {
		sum := 0
		for ; idx > 0; idx -= idx & -idx {
			sum += bit[idx]
		}
		return sum
	}

	R := n - 1
	for i := 0; i <= R; i++ {
		add(getIdx(paths[i].W), 1)
	}

	var totalPairs int64 = 0
	for i := 0; i < n; i++ {
		for R >= 0 && paths[i].L+paths[R].L > l {
			add(getIdx(paths[R].W), -1)
			R--
		}
		if R < 0 {
			break
		}
		idx := getIdx(w - paths[i].W)
		totalPairs += int64(query(idx))
		if paths[i].L*2 <= l && paths[i].W*2 <= w {
			totalPairs--
		}
	}

	return totalPairs / 2
}

func decompose(u int) {
	total := getSizes(u, -1)
	centroid := getCentroid(u, -1, total)

	allPaths := make([]Path, 0, total)
	allPaths = append(allPaths, Path{0, 0})

	for _, e := range adj[centroid] {
		if !deleted[e.to] {
			currentPaths = currentPaths[:0]
			dfs(e.to, centroid, 1, e.w)

			ans -= countPaths(currentPaths, l, w)
			allPaths = append(allPaths, currentPaths...)
		}
	}
	ans += countPaths(allPaths, l, w)

	deleted[centroid] = true
	for _, e := range adj[centroid] {
		if !deleted[e.to] {
			decompose(e.to)
		}
	}
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	buf := make([]byte, 1024*1024)
	scanner.Buffer(buf, bufio.MaxScanTokenSize)

	nextInt := func() int {
		scanner.Scan()
		res := 0
		for _, b := range scanner.Bytes() {
			res = res*10 + int(b-'0')
		}
		return res
	}

	if !scanner.Scan() {
		return
	}
	n := 0
	for _, b := range scanner.Bytes() {
		n = n*10 + int(b-'0')
	}
	if n == 0 {
		return
	}

	l = nextInt()
	w = nextInt()

	adj = make([][]Edge, n)
	for i := 1; i < n; i++ {
		p := nextInt() - 1
		weight := nextInt()
		adj[i] = append(adj[i], Edge{p, weight})
		adj[p] = append(adj[p], Edge{i, weight})
	}

	deleted = make([]bool, n)
	sz = make([]int, n)

	decompose(0)

	fmt.Println(ans)
}
```