首页 > 代码库 > 树形DP
树形DP
给一棵节点带权的树,找到一个有k个节点的子树,求这个子树的最大权值。
dp[u][k]表示以u为根的子树中包含u结点的大小为k的子树的最大权和
然后对u的每个子节点做分组背包,因为对于u的每个儿子,可以选择分配
1,2,3...k-1个节点给它
状态转移方程:
当节点大小为K时,可以由根节点为u,子树大小为k-t, 加上根节点为v,子树大小为t的状态转移得到(v为u的子节点),即:
dp[u][k] = max(dp[u][k] , dp[u][k-t]+dp[v][t]);//v是u的儿子节点
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std;//简单的树形DPint max(int a,int b){ return a>b?a:b;}const int inf = 1<<30;int n,k;int x[202];int dp[202][202];vector <int> List[202];void dfs(int u,int father){ int i,j; for(i=0;i<List[u].size();i++) { int v=List[u][i]; if(v==father) continue; dfs(v,u); for(j=k;j>=1;j--)//一定要倒序 { for(int t=1;t<=j;t++) dp[u][j]=max(dp[u][j] , dp[u][t]+dp[v][j-t]); } }}int main(){ scanf("%d %d",&n,&k); int i,j,a,b; for(i = 0;i <= n;i++) //清空list表 List[i].clear(); memset(dp,0,sizeof(dp)); dp[0][1]=0;//以0为根节点有且只有1个节点字数的最大权重 for(i=1;i<=n;i++){ scanf("%d %d",&b,&dp[i][1]);//以i为根节点有且只有1个节点字数的最大权重 List[i].push_back(b); List[b].push_back(i); } k++;//多加一个0节点 dfs(0,-1); printf("%d\n",dp[0][k]);//以0为根节点有且只有m个节点字数的最大权重 return 0;}
树形DP
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。