#include //#include using namespace std; //using namespace atcoder; using ll = long long; //using mint = modint998244353; int main(){ cin.tie(nullptr); ios_base::sync_with_stdio(false); /* dp(i, j) = 頂点iの部分木でステータスをjにするのに必要なコストの最小値 最初に dp(i, s_i) = c_i とし、dp(j, t)をマージするとき、 コストdp(j, t)、価値tの商品を選ぶナップサック問題。 このままだと間に合わないが2乗の木DPに落とし込める。 */ ll N, X; cin >> N >> X; vector> E(N); for (int i=1; i> p; p--; E[p].push_back(i); } vector s(N), c(N); for (int i=1; i> c[i] >> s[i]; vector sz(N); //頂点iの部分木のsの和 auto dfs=[&](auto self, ll from)->vector{ sz[from] = s[from]; ll ss = sz[from]; vector dp(ss+1, 1e18); dp[ss] = c[from]; for (auto to : E[from]){ auto pd = self(self, to); ll _ss=sz[to], nss=ss+_ss; vector merged(nss+1, 1e18); for (int i=0; i<=ss; i++){ for (int j=0; j<=_ss; j++){ merged[i+j] = min(merged[i+j], dp[i] + pd[j]); merged[i] = min(merged[i], dp[i]); } } swap(dp, merged); sz[from] = nss; ss = nss; } return dp; }; auto dp = dfs(dfs, 0); ll ans=1e18; for (int i=X; i