Main idea:
ACboy likes to play a strategy game. On a map, there are N castles, and each castle has certain treasures. In each game, ACboy allows to conquer M castles and obtain the treasures inside. However, due to geographical reasons, some castles cannot be directly conquered. To conquer these castles, you must first conquer other specific castles. Can you help ACboy figure out which M castles should be conquered to get as many treasures as possible?
Question idea:
This type of tree dp is more obvious
Consider that dp[u][k] represents the maximum value of k items selected from node u, because there is a dependency;
So pay attention to the state transition, pay special attention to the illegal state dp[u][0] not to be included in the transition
Since the whole picture is a forest, run all the trees and rely on the backpack
Run the grouping backpack for the forest in the whole picture
Code:
/*** keep hungry and calm CoolGuang! ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define d(x) printf("%lld\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17;
const ll maxn = 2e5+700;
const int mod= 1e9+7;
const int up = 1e9;
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
vector<int>v[maxn];
ll dp[2005][2005];
int num[maxn],in[maxn];
ll dpc[2005];
void dfs(int u){
dp[u][1] = num[u];
for(int e:v[u]){
dfs(e);
for(int k=m;k>=1;k--)
for(int j=1;j<=k-1;j++)
dp[u][k] = max(dp[u][k],dp[u][k-j]+dp[e][j]);
}
}
int main(){
while(~scanf("%lld%lld",&n,&m)&&n&&m){
for(int i=1;i<=n;i++) in[i] = 0,v[i].clear();
for(int i=1;i<=n;i++){
int x;read(x);read(num[i]);
if(x) v[x].push_back(i),in[i]++;
}
for(int i=1;i<=n;i++)
for(int k=0;k<=m;k++)
dp[i][k] = 0;
for(int i=1;i<=n;i++)
if(!in[i])
dfs(i);
for(int i=0;i<=m;i++) dpc[i] = 0;
for(int i=1;i<=n;i++){
if(!in[i]){
for(int k=m;k>=0;k--){
for(int j=0;j<=k;j++){
dpc[k] = max(dpc[k],dpc[k-j] + dp[i][j]);
}
}
}
}
ll ans = 0;
for(int i=0;i<=m;i++) ans = max(ans,dpc[i]);
printf("%lld\n",ans);
}
return 0;
}
/***
4 3
0 0
1 0
2 0
3 1
****/