[Luogu P2014]选课 (树形DP)
题面
传送门: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)相关推荐
- luogu P2014 选课
luogu P2014 选课 42行代码或成此题最X题解? 一看:树形dp f[i][j]表示以i为根的子树选了j个课所获得的最大学分 等等,课可以重复选! 要用背包搞搞喽 每次枚举子节点 对每个子节 ...
- 洛谷P2014【树形dp】
P2014 选课 时间限制 1.00s 内存限制 125.00MB 题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数 ...
- P2014 选课 (树形动规)
题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门课有个学分,每门课有一 ...
- UOJ #131 BZOJ 4199 luogu P2178【NOI2015】品酒大会 (后缀自动机、树形DP)
UOJ #131 BZOJ 4199 luogu P2178[NOI2015]品酒大会 (后缀自动机.树形DP) 水是水,但是写出了不少问题,因此写一发博客. https://www.luogu.or ...
- 背包类树形DP 选课题解
题目传送门; 我觉得题目给出0节点作为虚拟课程,也避免了我们要去想将若干个森林建成一棵树:将N个节点的森林建成了N+1条边的树: 其次,我们对这个题进行一个分析: 很容易想到F[x,t]表示以x为根的 ...
- 选课_ctsc1997_ssl1606_树形dp
Description 大学里实行学分.每门课程都有一定的学分,学生只要选修了这门课并考核通过就能获得相应的学分.学生最后的学分是他选修的各门课的学分的总和. 每个学生都要选择规定数量的课程.其中有些 ...
- 【Luogu】P1131时态同步(树形DP)
题目链接 甚矣吾衰也!这么简单的DP我都不会了 太恐怖了 树形DP,从子树里选出时间最长的来,剩下的调到这个最长时间即可. #include<cstdio> #include<cct ...
- Luogu P1122 最大子树和 树形DP
题目描述 小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题.一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题.于是当日课后,小明 ...
- 【Luogu】P2634聪聪可可(树形DP)
题目链接 水题,时限放得非常宽,暴力DP随便套上一波register就能卡过去. 唯一的遗憾是5A. 树形DP,s[i][j]表示以i为根的子树里距i的距离%3=j的点数,f[i]表示i为根的子树内一 ...
最新文章
- R语言plotly可视化:plotly可视化多个直方图、通过bingroup参数设置多个直方图使用相同的bins设置(Share bins between histograms)
- 开源三级联动,Vue.js编写省份、城市、区、县三级联动源码
- 2018/02/06
- HTML5标签的语义认知和理解
- python就是玩具_极客老爹的玩具DIY之路:Python + Kids + Building Stuff == Fun
- HDU 2376 Average distance
- oracle 的跨天查询,考勤跨天如何统计 - Oracle开发 - ITPUB论坛-中国专业的IT技术社区...
- 15分钟快速了解如何在Kubernetes中配置健康检查
- Oracle数据库 - 安装教程
- 和秋叶一起学PPT之段落排版与字体(课时四、五)
- MSN的聊天记录在哪里找到?
- pythonaot_热修复设计之AOT/JITdexopt 与 dex2oat (一)
- 威斯敏斯特教堂 名言_新教堂徽标设计师的视角分析
- 三维CAD设计软件的核心技术解析----工业软件讲坛第二次讲座
- 关于电压跟随器的那些事
- [06.21] LinkLabel 代码重构和我的SinaWeibo7 Project Todolist
- java四则运算思路_java四则运算
- 低风险整体式微服务演进第一部分
- 地址转换和端口映射及内网穿透的区别
- 删除文件提示需要计算机管理员权限,电脑怎么忽然删除文件夹需要管理员权限...