[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++)
[Luogu P2014]选课 (树形DP)的更多相关文章
- 洛谷P2014 选课 (树形dp)
10月1日更新.题目:在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门课有个学分 ...
- 选课 树形DP+多叉树转二叉树+dfs求解答案
问题 A: 选课 时间限制: 1 Sec 内存限制: 128 MB 题目描述 大 学里实行学分.每门课程都有一定的学分,学生只要选修了这门课并考核通过就能获得相应的学分.学生最后的学分是他选修的各门 ...
- vijos 1180 选课 树形DP
描述 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修了这M门课并考核通过就能获得 ...
- 『选课 树形dp 输出方案』
这道题的树上分组背包的做法已经在『选课 有树形依赖的背包问题』中讲过了,本篇博客中主要讲解将多叉树转二叉树的做法,以便输出方案. 选课 Description 学校实行学分制.每门的必修课都有固定的学 ...
- [vijos1880]选课<树形dp>
题目链接:https://www.vijos.org/p/1180 这是一道树形dp的裸题,唯一的有意思的地方就是用到了多叉树转二叉树 然后本蒟蒻写这一道水题就是因为以前知道这个知识点但是没有怎么去实 ...
- 树上背包DP Luogu P2014 选课
#include <cstdio> #include <cctype> #include <cstring> #include <algorithm> ...
- 【题解】Luogu p2014 选课 树型dp
题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门课有个学分,每门课有一 ...
- Codevs1378选课[树形DP|两种做法(多叉转二叉|树形DP+分组背包)---(▼皿▼#)----^___^]
题目描述 Description 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修 ...
- P2014 选课 (树形动规)
题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门课有个学分,每门课有一 ...
随机推荐
- nginx 1.12 负载均衡配置
负载均衡策略有以下几种: 请求轮询:round-robin,是默认策略,应用服务器的请求以循环方式分发,可以设置权重weight,默认权重均为1,因此每台后端服务器接受的请求数相同. 最少连接:lea ...
- Spring 注解形式AOP
AOP 面向切面编程,通过预编译的方式,在运行期通过动态代理实现一种技术,AOP可实现业务与切面的逻辑分离,降低耦合度 一.注解形式的AOP Aspect:切面 Joinpoint:连接点,要拦截的方 ...
- Python-对迭代器进行切片操作-itertools模块
案例: 对于某个文件,我只想读取到其中100~200行之间的内容,是否可以通过切片的方式进行读取? 我想: f = open() f[100:200] 可行? 如何解决这个问题? 方法1: 全部读取到 ...
- 061 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 08 一维数组总结
061 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 08 一维数组总结 本文知识点:一维数组总结 总结 注意点
- redis 开启AOF
找到redis 安装目录 例如 cd /usr/local/redis 打开 redis.conf 修改以下参数: # vi /usr/local/redis/etc/redis.conf appe ...
- 多测师讲解python_003.2练习题
# 1.分别打印100以内的所有偶数和奇数并存入不同的列表当中# 2.请写一段Python代码实现删除一个list = [1, 3, 6, 9, 1, 8]# 里面的重复元素不能用set# 3.将字符 ...
- OpenCV开发笔记(七十):红胖子带你傻瓜式编译VS2017x64版本的openCV4
前言 红胖子来也!!! opencv_contrib是opencv提供额外的工具,提供一些基础算法,之前编译了不带opencv_contrib的版本,不带opencv_contrib的cuda硬 ...
- HDU-1051 Wooden Sticks--线性动归(LIS)
题目大意:有n根木棍(n<5000),每根木棍有一个长度l和重量w(l,w<10000),现在要对这些木头进行加工,加工有以下规则: 1.你需要1分钟来准备第一根木头. 2.如果下一根木头 ...
- go读取excel表格数据
go读取excel表格数据 使用工具 github.com/Luxurioust/excelize 百度到的都是使用这个 实际上已经改名了 github.com/360EntSecGroup-Skyl ...
- 这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。
这是why哥的第 70 篇原创文章 从Dubbo的一次提交开始 故事得从前段时间翻阅 Dubbo 源码时,看到的一段代码讲起. 这段代码就是这个: org.apache.dubbo.rpc.RpcCo ...