package main

import (
	"fmt"
)

type item struct {
	id         int
	price      int
	importance int
	parentId   int
	value      int
}

type goods struct {
	master      item
	attachments []item
}

// // 得到动态规划,01背包问题的  列数据
func getGoodsGroup(itemNumber int) map[int]goods {
	goodsMap := make(map[int]goods)
	for i := 0; i < itemNumber; i++ {
		good := item{}
		good.id = i + 1
		fmt.Scan(&good.price, &good.importance, &good.parentId)
		good.value = good.price * good.importance
		if good.parentId == 0 {
			// 这是个主件商品
			goods, _ := goodsMap[good.id]
			master := item{
				id:         good.id,
				price:      good.price,
				importance: good.importance,
				parentId:   good.parentId,
				value:      good.price * good.importance,
			}
			goods.master = master
			goodsMap[good.id] = goods
		} else {
			// 这是个附件商品
			parentGoods, _ := goodsMap[good.parentId]
			// 所属主件存在
			parentGoods.attachments = append(parentGoods.attachments, item{
				id:         good.id,
				price:      good.price,
				importance: good.importance,
				parentId:   good.parentId,
				value:      good.price * good.importance,
			})
			goodsMap[good.parentId] = parentGoods

		}
	}
	return goodsMap
}

func main() {
	var totalPrice, itemNumber int
	fmt.Scan(&totalPrice, &itemNumber)
	// 得到动态规划,01背包问题的  列数据
	goodsMap := getGoodsGroup(itemNumber)

	dp := make([]int, totalPrice+1)
	for _, goods := range goodsMap {
		tempDp := make([]int, totalPrice+1)
		copy(tempDp, dp) // 做一个临时变量,防止上一个物品最优解的dp,被污染。
		for j := 1; j <= totalPrice; j++ {
			// 核心原理是:当前选择的满意度 + (背包-当前选择的价格)的满意度 与上一个物品的最优结果做对比
			// 所以(背包-当前选择的价格)的满意度不能收到污染,等本轮j循环完了,再修改上一个物品的最优解
			attachments := 0
			// 只买主件
			if j-goods.master.price >= 0 {
				attachments = goods.master.value + dp[j-goods.master.price]
				tempDp[j] = max(tempDp[j], attachments)
			}

			// 买主件和一个附件
			if len(goods.attachments) > 0 {
				if j-goods.master.price-goods.attachments[0].price >= 0 {
					attachments = goods.master.value + goods.attachments[0].value + dp[j-goods.master.price-goods.attachments[0].price]
					tempDp[j] = max(tempDp[j], attachments)
				}
			}

			if len(goods.attachments) > 1 {
				// 买主件和另一个附件
				if j-goods.master.price-goods.attachments[1].price >= 0 {
					attachments = goods.master.value + goods.attachments[1].value + dp[j-goods.master.price-goods.attachments[1].price]
					tempDp[j] = max(tempDp[j], attachments)
				}

				// 买主件和两个附件
				if j-goods.master.price-goods.attachments[0].price-goods.attachments[1].price >= 0 {
					attachments = goods.master.value + goods.attachments[0].value + goods.attachments[1].value + dp[j-goods.master.price-goods.attachments[0].price-goods.attachments[1].price]
					tempDp[j] = max(tempDp[j], attachments)
				}
			}
		}
		dp = tempDp
		// fmt.Println(masterId, dp)
	}

	fmt.Println(dp[totalPrice])
}

func max(a, b int) int {
	if a > b {
		return a
	} else {
		return b
	}
}