题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561
思路:树形dp+01背包 //看注释可以懂
用vector建树更简单。
代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> using namespace std; #define ll long long const int maxn=2e2+5; const int INF=0x3f3f3f3f; ///dp[i][j] 表示以i为跟节点的树,选其中的j个节点可以达到的最大值 int dp[maxn][maxn]; vector<int>v[maxn]; int N,M,x,a[maxn]; void dfs(int n,int m) { dp[n][1]=a[n]; int len=v[n].size(); for(int i=0; i<len; i++) ///01背包第一层循环 { if(m>1) dfs(v[n][i],m-1); for(int j=m-1; j>=1; j--) ///第二层循环,相当于背包的重量,-1的原因是至少有一个节点是根节点 for(int k=1; k<=j; k++) ///k是在第i棵树上选K个子节点 dp[n][j+1]=max(dp[n][j+1],dp[n][j+1-k]+dp[v[n][i]][k]); ///+1的目的就是保证至少选一个节点是根节点 } } int main() { //freopen("in.txt","r",stdin); while(scanf("%d%d",&N,&M) && N+M) { memset(dp,0,sizeof(dp)); memset(a,0,sizeof(a)); for(int i=0; i<=N; i++) v[i].clear(); for(int i=1; i<=N; i++) { scanf("%d%d",&x,&a[i]); v[x].push_back(i); } dfs(0,M+1); printf("%d\n",dp[0][M+1]); } return 0; }
时间: 2024-12-23 14:18:41