题面

传送门:https://www.luogu.org/problemnew/show/P2014


Solution

这是一道十分经典的树形DP题,这种类型的树形DP有一种很普遍的解法。

首先,观察题目,我们把这道题转换一下:给定一颗树,选出包含1号节点(根)的一颗子树,使得点权和最大

我们可以这样子定义状态:

f[i][j] 表示以i为根节点的子树,选出j个节点,所能达到的最大点权值

对于二叉树来说,转移很显然,就是枚举左子树分配多少个节点,就可以对应的得出右子树能分配到多少个节点,对所有情况取最大值就好。

对于多叉树来说,问题就没有那么简单了,这里,我们有两个方案可以解决这个问题:

一是多叉树转二叉树,

二是树上背包。

因为我不会多叉树转二叉树,所以在这里我主要讲一讲第二种方法。

我们一般在树上做的是多重背包问题。

我以本题为例子,讲一下树上如何做多重背包。

首先,我们肯定要一层循环枚举子树(可以类似为背包问题中枚举第几件物品)

第二层循环我们得枚举当前以节点的子树能分配的节点数(可以类似为背包问题中枚举背包容量)

*这一层循环一定要从后往前枚举,类似与背包压在一维做的做法*

第三层循环我们就可以枚举当前子树分配多少个节点了(可以类似多重背包中枚举第i件物品要几件)

下面是这种枚举在这道题应用的代码:

1     for(int i=0;i<int(e[x].size());i++)//枚举子树
2     {
3         int temp=dfs(e[x][i]);//先把子树的f递归下去算出来
4         tot+=temp;//tot记录到当前子树为止总节点数
5         for(int j=tot;j>=1;j--)//枚举自己这颗树的总分配数
6             for(int k=0;k<=temp;k++)//枚举子树分配多少个节点
7                 if(j-k>=1)
8                     f[x][j]=max(f[x][j],f[x][j-k]+f[e[x][i]][k]);
9     }

树上背包一般看上去是三重循环,非常恐怖。

但事实上,根据一堆证明(不会证),其复杂度为两重循环。

所以复杂度应该是O(能过)

复杂度是O(N*N*M)


Code

树上背包有成吨的细节,建议参考代码

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
long long read()
{long long x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f;
}
const int N=300+10;
vector <int> e[N];
long long n,m,f[N][N],v[N];
int dfs(int x)
{int tot=1;f[x][1]=v[x];for(int i=0;i<int(e[x].size());i++){int temp=dfs(e[x][i]);tot+=temp;for(int j=tot;j>=1;j--)for(int k=0;k<=temp;k++)if(j-k>=1)f[x][j]=max(f[x][j],f[x][j-k]+f[e[x][i]][k]);}return tot;
}
int main()
{n=read(),m=read();for(int i=0;i<=n;i++)e[i].reserve(4);for(int i=1;i<=n;i++){e[read()].push_back(i);v[i]=read();}dfs(0);printf("%lld",f[0][m+1]);return 0;
}

正解(c++)

转载于:https://www.cnblogs.com/GoldenPotato/p/9440154.html

[Luogu P2014]选课 (树形DP)相关推荐

  1. luogu P2014 选课

    luogu P2014 选课 42行代码或成此题最X题解? 一看:树形dp f[i][j]表示以i为根的子树选了j个课所获得的最大学分 等等,课可以重复选! 要用背包搞搞喽 每次枚举子节点 对每个子节 ...

  2. 洛谷P2014【树形dp】

    P2014 选课 时间限制 1.00s 内存限制 125.00MB 题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数 ...

  3. P2014 选课 (树形动规)

    题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门课有个学分,每门课有一 ...

  4. UOJ #131 BZOJ 4199 luogu P2178【NOI2015】品酒大会 (后缀自动机、树形DP)

    UOJ #131 BZOJ 4199 luogu P2178[NOI2015]品酒大会 (后缀自动机.树形DP) 水是水,但是写出了不少问题,因此写一发博客. https://www.luogu.or ...

  5. 背包类树形DP 选课题解

    题目传送门; 我觉得题目给出0节点作为虚拟课程,也避免了我们要去想将若干个森林建成一棵树:将N个节点的森林建成了N+1条边的树: 其次,我们对这个题进行一个分析: 很容易想到F[x,t]表示以x为根的 ...

  6. 选课_ctsc1997_ssl1606_树形dp

    Description 大学里实行学分.每门课程都有一定的学分,学生只要选修了这门课并考核通过就能获得相应的学分.学生最后的学分是他选修的各门课的学分的总和. 每个学生都要选择规定数量的课程.其中有些 ...

  7. 【Luogu】P1131时态同步(树形DP)

    题目链接 甚矣吾衰也!这么简单的DP我都不会了 太恐怖了 树形DP,从子树里选出时间最长的来,剩下的调到这个最长时间即可. #include<cstdio> #include<cct ...

  8. Luogu P1122 最大子树和 树形DP

    题目描述 小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题.一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题.于是当日课后,小明 ...

  9. 【Luogu】P2634聪聪可可(树形DP)

    题目链接 水题,时限放得非常宽,暴力DP随便套上一波register就能卡过去. 唯一的遗憾是5A. 树形DP,s[i][j]表示以i为根的子树里距i的距离%3=j的点数,f[i]表示i为根的子树内一 ...

最新文章

  1. R语言plotly可视化:plotly可视化多个直方图、通过bingroup参数设置多个直方图使用相同的bins设置(Share bins between histograms)
  2. 开源三级联动,Vue.js编写省份、城市、区、县三级联动源码
  3. 2018/02/06
  4. HTML5标签的语义认知和理解
  5. python就是玩具_极客老爹的玩具DIY之路:Python + Kids + Building Stuff == Fun
  6. HDU 2376 Average distance
  7. oracle 的跨天查询,考勤跨天如何统计 - Oracle开发 - ITPUB论坛-中国专业的IT技术社区...
  8. 15分钟快速了解如何在Kubernetes中配置健康检查
  9. Oracle数据库 - 安装教程
  10. 和秋叶一起学PPT之段落排版与字体(课时四、五)
  11. MSN的聊天记录在哪里找到?
  12. pythonaot_热修复设计之AOT/JITdexopt 与 dex2oat (一)
  13. 威斯敏斯特教堂 名言_新教堂徽标设计师的视角分析
  14. 三维CAD设计软件的核心技术解析----工业软件讲坛第二次讲座
  15. 关于电压跟随器的那些事
  16. [06.21] LinkLabel 代码重构和我的SinaWeibo7 Project Todolist
  17. java四则运算思路_java四则运算
  18. 低风险整体式微服务演进第一部分
  19. 地址转换和端口映射及内网穿透的区别
  20. 删除文件提示需要计算机管理员权限,电脑怎么忽然删除文件夹需要管理员权限...

热门文章

  1. putty 显示 ubuntu的文件乱码
  2. 【Eclipse提高开发速度-插件篇】安装VJET插件,JS等提示开发插件
  3. CHIL-SQL-FIRST() 函数
  4. NSIndexPath类
  5. 学习VIM编辑器的使用
  6. 类linux系统/proc/sysrq-trigger文件功能作用
  7. 移动时代的互联网格局变化
  8. IE滤镜实现透明度/阴影/渐变等特效
  9. crontab 用法
  10. caffe loss