← Home
```go
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

// Use a large enough infinity that fits in int64
const INF int64 = 1e16

type Item struct {
	c, d int64
}

var (
	adj   [][]int
	goods []Item
)

func main() {
	// Configure scanner for fast I/O
	scanner := bufio.NewScanner(os.Stdin)
	const maxCapacity = 2048 * 1024
	buf := make([]byte, maxCapacity)
	scanner.Buffer(buf, maxCapacity)
	scanner.Split(bufio.ScanWords)

	// Helper to read int
	readInt := func() int {
		scanner.Scan()
		val, _ := strconv.Atoi(scanner.Text())
		return val
	}

	// Helper to read int64
	readInt64 := func() int64 {
		scanner.Scan()
		val, _ := strconv.ParseInt(scanner.Text(), 10, 64)
		return val
	}

	// Read N and B
	if !scanner.Scan() {
		return
	}
	nStr := scanner.Text()
	n, _ := strconv.Atoi(nStr)
	b := readInt64()

	adj = make([][]int, n+1)
	goods = make([]Item, n+1)

	// Read items
	// Item 1
	goods[1] = Item{c: readInt64(), d: readInt64()}

	// Items 2 to n
	for i := 2; i <= n; i++ {
		c := readInt64()
		d := readInt64()
		x := readInt()
		goods[i] = Item{c: c, d: d}
		adj[x] = append(adj[x], i)
	}

	// Run DP
	res := dfs(1)

	// Find max k such that cost <= b
	// Root coupon is available, so we check res[k][1]
	ans := 0
	for k := len(res) - 1; k >= 0; k-- {
		if res[k][1] <= b {
			ans = k
			break
		}
	}
	fmt.Println(ans)
}

// Returns a slice of [2]int64
// index k -> cost to buy k items
// [0] -> coupon NOT available
// [1] -> coupon AVAILABLE
func dfs(u int) [][2]int64 {
	// dp0: state 0 costs. Init: buy u at full price or don't buy
	// dp1: state 1 partial costs (only force buy u with coupon).
	
	// Initial state for leaf u
	// dp0: [0 items: 0, 1 item: c_u]
	dp0 := []int64{0, goods[u].c}
	
	// dp1: [0 items: INF, 1 item: c_u - d_u]
	dp1 := []int64{INF, goods[u].c - goods[u].d}

	sz := 1

	for _, v := range adj[u] {
		childRes := dfs(v)
		childSz := len(childRes) - 1
		newSz := sz + childSz

		// Allocate new arrays initialized to INF
		newDp0 := make([]int64, newSz+1)
		newDp1 := make([]int64, newSz+1)
		for k := 0; k <= newSz; k++ {
			newDp0[k] = INF
			newDp1[k] = INF
		}

		// Merge
		for i := 0; i <= sz; i++ {
			// Merge dp0 with child state 0
			// If we don't use coupon for u (or not buy u), child cannot use coupon
			c0 := dp0[i]
			if c0 < INF {
				for j := 0; j <= childSz; j++ {
					val := c0 + childRes[j][0]
					if val < newDp0[i+j] {
						newDp0[i+j] = val
					}
				}
			}

			// Merge dp1 with child state 1
			// If we force buy u with coupon, child can use coupon
			c1 := dp1[i]
			if c1 < INF {
				for j := 0; j <= childSz; j++ {
					val := c1 + childRes[j][1]
					if val < newDp1[i+j] {
						newDp1[i+j] = val
					}
				}
			}
		}
		
		dp0 = newDp0
		dp1 = newDp1
		sz = newSz
	}

	// Combine to produce result
	// res[k][0] = dp0[k]
	// res[k][1] = min(dp1[k], dp0[k]) 
	// (Since coupon available allows us to either use it (dp1) or behave as if not available (dp0))
	res := make([][2]int64, sz+1)
	for i := 0; i <= sz; i++ {
		res[i][0] = dp0[i]
		
		minState1 := dp1[i]
		if dp0[i] < minState1 {
			minState1 = dp0[i]
		}
		res[i][1] = minState1
	}

	return res
}
```