```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
}
```