【NOIP2017提高A组集训10.25】摘Galo (树形dp)
Description
0v0在野外看到了一棵Galo树,看到食物的0v0瞪大了眼睛,变成了OvO。
这棵Galo树可以看做是一棵以1号点为根的n个点的有根数,除了根节点以外,每个节点i都有一个Galo,美味度为w[i]。
OvO发现,如果她摘下了i号Galo,那么i的子树中的Galo以及i到根的路径上的其他Galo都会死掉。
OvO的袋子只能装k个Galo,她的嘴巴里还能叼1个,请问她所摘Galo的美味度之和的最大值是多少?
Input
第一行两个正整数n,k。
第二行到第n行,第i行两个正整数f[i],w[i],表示i号点的父亲为f[i] (保证x[i]
Output
一行一个非负整数,为最大美味值。
Sample Input
4 1
1 10
2 3
2 6
Sample Output
10
Data Constraint
30% n,k<=200
30% n*k*k<=10^7
40% n*k<=10^7
对于所有数据,n,k,w[i]<=10^5
Hint
尽管OvO最多可以摘两个Galo,但是最优情况是只摘下第二个点的Galo,美味度为10。
题解
这题朴素的dp复杂度是O(n∗k2)O(n*k^2),做法就是选课
其实可以做到O(n∗k)O(n*k),做法也不难,代码比朴素还短,只需要搞出来dfs序,然后在dfs序上dp就好了
为什么是O(n∗k)O(n*k)呢?
因为我们只需要遍历一遍状态,然后每一个状态由于是在dfs序上,所以只有两种转移:
1.选择它本身,并跳过它的子树,也就是在dfs序上加上它的子树大小
2.不选它本身,进入它的子树,也就是在dfs序上加1
然后就少了好多冗余状态。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<vector>
#define ll long long
using namespace std;
inline int read(){int x=0;char ch=' ';int f=1;while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();if(ch=='-')f=-1,ch=getchar();while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;
}
struct edge{int to,next;
}e[200001];
int n,k,tot;
int head[100001];
inline void addedge(int x,int y){e[++tot].to=y;e[tot].next=head[x];head[x]=tot;
}
vector<ll> f[100005];
ll w[100005];
int size[100005];
int dfn[100005],dfn_clock;
inline void dfs(int x,int fa){size[x]=1;dfn[++dfn_clock]=x;for(int i=head[x];i;i=e[i].next){int u=e[i].to;if(u==fa)continue;dfs(u,x);size[x]+=size[u];}
}
inline ll dp(int i,int j){if(i>n)return 0;if(j==0)return 0;if(f[i][j])return f[i][j];f[i][j]=max(f[i][j],dp(i+size[dfn[i]],j-1)+w[dfn[i]]);f[i][j]=max(f[i][j],dp(i+1,j));return f[i][j];
}
int main(){freopen("galo.in","r",stdin);freopen("galo.out","w",stdout);n=read();k=read()+1;for(int i=2;i<=n;i++){int fa=read();w[i]=read();addedge(fa,i);addedge(i,fa);}dfs(1,0);for(int i=1;i<=n;i++){f[i].resize(k+1);}printf("%lld",dp(1,k));return 0;
}
【NOIP2017提高A组集训10.25】摘Galo (树形dp)相关推荐
- JZOJ 5426. 【NOIP2017提高A组集训10.25】摘Galo
Description 0v0在野外看到了一棵Galo树,看到食物的0v0瞪大了眼睛,变成了OvO. 这棵Galo树可以看做是一棵以1号点为根的n个点的有根数,除了根节点以外,每个节点i都有一个Gal ...
- 【JZOJ 5426】【NOIP2017提高A组集训10.25】摘Galo
Description 0v0在野外看到了一棵Galo树,看到食物的0v0瞪大了眼睛,变成了OvO. 这棵Galo树可以看做是一棵以1号点为根的n个点的有根数,除了根节点以外,每个节点i都有一个Gal ...
- JZOJ5426. 【NOIP2017提高A组集训10.25】摘Galo
Description 0v0在野外看到了一棵Galo树,看到食物的0v0瞪大了眼睛,变成了OvO. 这棵Galo树可以看做是一棵以1号点为根的n个点的有根数,除了根节点以外,每个节点i都有一个Gal ...
- JZOJ 5421. 【NOIP2017提高A组集训10.25】嘟嘟噜
Description 由于众所周知的原因, 冈部一直欠真由理一串香蕉. 为了封上真由理的嘴, 冈部承诺只要真由理回答出这个问题, 就给她买一车的香蕉: 一开始有n 个人围成一个圈, 从1 开始顺时针 ...
- JZOJ 5425. 【NOIP2017提高A组集训10.25】数论
Description 聪明的0v0正在学习莫比乌斯反演. 她看到了这样的一道题:有n*m个人站成了一个n*m的方阵-- 剩下的题面,聪明的0v0不记得了.但是,她通过自己高超的数论技巧,给出了一个转 ...
- JZOJ 5422. 【NOIP2017提高A组集训10.25】天才绅士少女助手克里斯蒂娜
Description Input 第一行两个整数n;m 表示电子个数和询问个数. 接下来n 行, 每行两个整数x; y 表示vi. 接下来m 行, 每行形如1 p x y 或2 l r, 分别表示两 ...
- 5424. 【NOIP2017提高A组集训10.25】凤凰院凶真
这是一道DP题,然后做的时候发现,DP式子死活推不出来. 题目大意(本人实在是不想复制了呵-- 给出A,B序列 找出他们的最长公共严格递增子序列 明确,这是一道DP 所以设状态fi,jf_{i,j}f ...
- JZOJ5424. 【NOIP2017提高A组集训10.25】凤凰院凶真
题解 题目的意思是求两个序列的最长公共上升子序列. 就此可以联想到求两个序列的最长公共子序列: 设fi,jf_{i,j}表示a序列处理到i,b序列处理j的最长公共子序列, 转移很简单. 现在要满足公共 ...
- JZOJ5422. 【NOIP2017提高A组集训10.25】天才绅士少女助手克里斯蒂娜
题解 viv_i是一个向量, 那么需要求的就是叉积的平方和. 假设v1=(x1,y1),v2=(x2,y2)v_1=(x_1,y_1),v_2=(x_2,y_2) 那么v1∗v2=x1∗y2−x2∗y ...
最新文章
- tcp报文格式_面试必备TCP(一):三次握手
- css行高line-height的用法
- OutOfRangeError closed and has insufficient elements (requested 512, current size 362)
- 【408预推免复习】计算机网络(谢希仁第七版)第一章——概述
- 二分图带权最大匹配费用流_一文掌握阻抗匹配
- c++ set遍历_Python算法学习之图与图的遍历
- linux dns配置bind9,DNS服务(bind9)配置过程
- 程序员获取编程灵感的10 种方式
- C++ | Qt 获取局域网中存在的主机(IP以及主机名)
- Qt工作笔记-QMap查找时要注意的问题(使用contains)
- 关于windows重装原先wubi安装的Ubuntu启动项消失的解决办法
- c语言计算器模拟程序,【C语言】 模拟计算器
- python函数装饰器有什么用_Python @函数装饰器及用法(超级详细)
- 郁闷,IT厂商认证考试没有通过!
- 一个桌面系统的微信公众号开发
- 终端一直显示 (master) ,即终端一直处于master分支下的取消办法
- 基于51单片机的交通灯仿真方案原理图设计一个数码管
- 科普:指纹识别的工作原理
- 如何查看电脑支持的最大内存是多少
- Shape Inpainting using 3D Generative Adversarial Network and Recurrent Convolutional Networks
热门文章
- 【李佳辉_周报_2022.10.30】
- avr c语言编译器,AVR单片机C语言编译器-20210409071159.docx-原创力文档
- Android Banner
- 盘数几则热门微信好友诈骗套路
- java如何获取一个对象的大小
- 电脑录像软件推荐?分享3款,简单好用且方便
- (1)定义圆Circle类,包含radius半径属性,求面积方法,求周长方法,返返回圆对象的详细信息的方法(2)在测试类中创建长度为5的Circle[]数组,用来装5个圆对象
- Postman + Pre-resuestScript:预请求脚本发送POST请求
- c语言中的除号什么作用,c语言中除号用什么表示
- angular快速入门教程