You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.
# include <bits/stdc++.h>
using namespace std ;
const int N = 110 ;
// 邻接表
int h [ N ] , ne [ N ] , e [ N ] , idx ;
void add ( int a , int b ) {
e [ idx ] = b , ne [ idx ] = h [ a ] , h [ a ] = idx + + ;
}
int n , m ; // n个物品,m个空间上限
int v1 [ N ] , w1 [ N ] , v [ N ] , w [ N ] ; // 因为在生成 dfs序的过程中, 本质是重新将原来的输入次序重排了, 需要记录原来的体积、价值, 和新的体积、价值
int f [ N ] [ N ] ; // 表示在以u为根的子树中, 用大小为j的包能取得的最大价值
int sz [ N ] ; // 以i为根结点的子树中结点的个数
int dfn [ N ] , ts ; // 时间戳
/**
* 功能: dfs序
* 本质: 就是执行一遍树的dfs,找一个辅助数组记录一下dfs序
* @param u 结点编号
*/
void dfs ( int u ) {
dfn [ u ] = + + ts ; // 记录结点u在dfs序中是第几个,下标从1开始,时间戳
// 维护子树的结点个数
sz [ ts ] = 1 ; // 以dfs序中ts号为根的子树中结点个数
w [ ts ] = w1 [ u ] ; // 将原来树中p号结点的体积转移到ts号dfs序的结点体积上去
v [ ts ] = v1 [ u ] ; // 将原来树中p号结点的价值转移到ts号dfs序的结点价值上去
for ( int i = h [ u ] ; ~ i ; i = ne [ i ] ) {
int j = e [ i ] ;
dfs ( j ) ;
// 收集所有子结点的个数
sz [ dfn [ u ] ] + = sz [ dfn [ j ] ] ;
}
}
int main ( ) {
// 初始化
memset ( h , - 1 , sizeof h ) ;
cin > > n > > m ;
int root ;
for ( int i = 1 ; i < = n ; i + + ) {
int p ;
cin > > w1 [ i ] > > v1 [ i ] > > p ;
if ( p = = - 1 )
root = i ; // 记录根结点
else
add ( p , i ) ; // 维护邻接表
}
// dfs序
dfs ( root ) ;
// 倒着做01背包
for ( int i = n ; i > = 1 ; i - - )
for ( int j = 1 ; j < = m ; j + + ) {
f [ i ] [ j ] = f [ i + sz [ i ] ] [ j ] ; // 放弃物品i
if ( j > = w [ i ] ) f [ i ] [ j ] = max ( f [ i ] [ j ] , f [ i + 1 ] [ j - w [ i ] ] + v [ i ] ) ; // 选择物品i
}
// 输出
printf ( " %d \n " , f [ 1 ] [ m ] ) ;
return 0 ;
}