没有上司的舞会|codevs1380|luoguP1352|树形DP|Elena
没有上司的舞会
Ural大学有N个职员,编号为1~N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。
第一行一个整数N。(1<=N<=6000)
接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)
接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。
最后一行输入0,0。
输出最大的快乐指数。
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
5
各个测试点1s
一个节点的父亲就是它的直接上司,没有职员愿和直接上司一起与会 就是要求节点和父节点不能同时选择,注意题目输入边的关系时输入u、v表示的是v是u的父亲。题目没有给根节点,所以我这里用边表来储存树,边读入边标记有父亲的点flag值为1,读入结束后再扫描一遍flag数组,flag值为0的节点就是根节点了,因为它没有父亲。接着我们就直接写一个函数dp根节点。
那么这个dp的递归函数该怎么写呢?我们先来想办法推出状态转移方程。
对于每个节点,我们都有取和不取两个操作。f[i][0]和f[i][1]分别表示i节点取和不取得到的最大值。虽然题目里给定点的权值范围是(-128<=Ri<=127),但是我们要首先大胆地肯定一点:f[i][0]不可能小于0,f[i][1]不可能小于i点的权值也就是dis[i]。为什么?因为我们要求最大的价值,而如果当下面的节点权值都为负数会出现“越取越小”的情形时,我们就干脆一个节点都不取,这样子取得的价值就直接为0,f[i][1]不可能小于i点的权值也是同理:取了i点的权值后,若i的儿子权值都是负数,越取越小,则干脆不取,这样f[i][1]就会变成dis[i],也不可能小于dis[i]。所以f[i][0]不可能小于0,f[i][1]不可能小于i点的权值也就是dis[i]。
注:edge[j].to存储的是i节点的儿子节点,详情可以看我的代码中边表的实现;0表示不取,1表示取。
因为这是树形dp,我们当然是从父亲递归到每一个儿子啦。对于每个节点,我们都有取和不取两个操作。如果i节点取的话,i节点的儿子节点就一定不能取,所以f[i][1]+=f[edge[j].to][0]。如果有人问我为什么f[i][1]是“+=”f[edge[j].to][0]而不是“=”,那我只能说:人家又不是只有一个儿子,你如果把i点取的值直接等于儿子不取的最大价值的话,那简直就是事故现场,你可以想想如果这么做你为什么有存储f[i][1]的必要,因为f[i][1]的值在f[edge[j].to][0]就存储了。而如果i节点不取的话,i节点的儿子就有了两种选择:取和不取。而对于这两种选择,我们当然选择更大的价值啦。所以f[i][0]+=max(f[edge[j].to][0],f[edge[j].to][1]);。
然后我再拿出一段代码分析一下,也就是核心代码:dp的函数:
void dp(int i)
{
for (int j=head[i]; j; j=edge[j].next) {//遍历每一条以i为起点的边j。
dp(edge[j].to);//先递归一下待会需要用到的儿子节点,你可以理解成准备dp需要用的东西。
f[i][1]+=f[edge[j].to][0];//这里不需要用到max函数,我前面已经解释过了最大值不可能是负数,所以不需要。这里是取i点的最大价值。
f[i][0]+=max(f[edge[j].to][0],f[edge[j].to][1]);//这是不取i点的最大价值。
}
f[i][1]+=dis[i];//1表示当前点要取,既然取了这个点,就要加上这个点的权值。
return;
}
还是不懂的同学可以自己拿笔和纸模拟一下,其实我的核心代码很短的。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
int read()
{
int f=,x=; char c=getchar();
while (c>''||c<'') {if (c=='-') f=-; c=getchar();}
while (c>='' && c<='') {x=x*+c-''; c=getchar();}
return x*f;
}
int num_edge,head[],f[][],n,dis[],u,v,gen;
long long MAX=;
bool flag[];
struct Edge
{
int next;
int to;
}edge[];
void Add_edge(int from,int to)
{
edge[++num_edge].next=head[from];
edge[num_edge].to=to;
head[from]=num_edge;
}
void dp(int i)
{
for (int j=head[i]; j; j=edge[j].next) {
dp(edge[j].to);
f[i][]+=f[edge[j].to][];
f[i][]+=max(f[edge[j].to][],f[edge[j].to][]);
}
f[i][]+=dis[i];
return;
}
int main()
{
n=read();
for (int i=; i<=n; i++) dis[i]=read();
for (int i=; i<=n-;i++) {
u=read(); v=read();
Add_edge(v,u);
flag[u]=;
}
u=read();
v=read();
for (int i=; i<=n; i++)
if (flag[i]==) {
gen=i;
break;
}
dp(gen);
if (f[gen][]>f[gen][]) printf("%d\n",f[gen][]);
else printf("%d\n",f[gen][]);
return ;
}
没有上司的舞会
有问题可以直接在评论里面提问,有需要转载的请得到我的允许,否则按侵权处理。
Elena loves NiroBC forever!
没有上司的舞会|codevs1380|luoguP1352|树形DP|Elena的更多相关文章
- 二叉苹果树|codevs5565|luoguP2015|树形DP|Elena
二叉苹果树 题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的 ...
- C++ luogu1352没有上司的舞会 from_树形DP
luogu1352没有上司的舞会 分析(树形DP模板题): 没学树形DP的,看一下. 把该题抽象到一颗树中,设i的下属就是他的儿子,则有两种情况: 如果i参加,他的儿子就不能参加. 如果i不参加,他的 ...
- 树形DP 学习笔记
树形DP学习笔记 ps: 本文内容与蓝书一致 树的重心 概念: 一颗树中的一个节点其最大子树的节点树最小 解法:对与每个节点求他儿子的\(size\) ,上方子树的节点个数为\(n-size_u\) ...
- CodeVS1380 没有上司的舞会 [树形DP]
题目传送门 没有上司的舞会 题目描述 Description Ural大学有N个职员,编号为1~N.他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.每个职员有一个 ...
- 【codevs1380】没有上司的舞会 树形dp
题目描述 Ural大学有N个职员,编号为1~N.他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.每个职员有一个快乐指数.现在有个周年庆宴会,要求与会职员的快乐指数 ...
- luoguP1352没有上司的舞会(树形DP)
题目链接:https://www.luogu.org/problemnew/show/P1352 题意:给定n个结点,每个结点有一个权值,给n-1条边,n个结点构成一棵树.并且规定一个结点的父结点如果 ...
- 『没有上司的舞会 树形DP』
树形DP入门 有些时候,我们需要在树形结构上进行动态规划来求解最优解. 例如,给定一颗\(N\)个节点的树(通常是无根树,即有\(N-1\)条无向边),我们可以选择任意节点作为根节点从而定义出每一颗子 ...
- [luogu]P1352 没有上司的舞会[树形DP]
本Lowbee第一次写树形DP啊,弱...一个变量写错半天没看出来...... 题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点 ...
- 洛谷 P1352 没有上司的舞会【树形DP】(经典)
<题目链接> <转载于>>> > 题目描述: 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的 ...
随机推荐
- phpbbchina恢复上线
上个月已经把ICP备案重新办过了, 但是一直在忙着应付工作上的事. 从上周末开始经过数天的努力, 将 phpbbchina 恢复上线了. 时间一晃, 正好十年. 目前能找到的最新的数据是2008-10 ...
- Seaslog安装和参数配置
详细文档访问:https://github.com/Neeke/SeasLog/blob/master/README_zh.md 源码安装步骤: 1.先下载Seaslog源码,下载地址:http:// ...
- 电子证书 DER & PEM & CRT & CER
原文链接: http://blog.csdn.net/zqt520/article/details/26966603 证书与编码 本至上,X.509证书是一个数字文档,这个文档根据RFC 5280来编 ...
- appium 获取android 粘贴板上的内容
appium 新版本增加了获取粘贴板的内容.如果使用appium旧版本,获取粘贴板的内容不是那么容易的,甚至百度谷歌各种搜,都无法找到合适的解决方法.新版本获取android 粘贴板内容就显得很容易了 ...
- redis 的消息订阅和消息队列的功能比较
消息队列常用的有 rabitMQ.kafka等.缓存服务器 redis 也可以做消息队列使用,他们的特点对比如下 消息协议: 消息队列支持包括AMQP,MQTT,Stomp等,并且支持 JMS 规范 ...
- rinetd 一个linux下的端口转发工具
inux下使用iptables实现端口转发,配置较为复杂,使用rinetd工具可以实现快速配置和修改端口转发. 例:本机ip:1.1.1.1 需要实现访问本机的8080端口,自动转发到2.2.2.2 ...
- Python测试DB2连通性
Python测试数据库连通性: #!/usr/bin/python27 #encoding: utf-8 import ibm_db import os import sys def find_db( ...
- jupyter修改根目录
找到jupyter的快捷方式,然后修改目标: 首先在快捷方式上右键单击,选择属性: 然后将目标那里替换自己想要的目录: 网上有的教程说保留%USERPROFILE%,其实这是受系统对路径解析的影响的. ...
- 2. Tensorflow的数据处理中的Dataset和Iterator
1. Tensorflow高效流水线Pipeline 2. Tensorflow的数据处理中的Dataset和Iterator 3. Tensorflow生成TFRecord 4. Tensorflo ...
- Java知多少(84)图形界面之布局设计
在界面设计中,一个容器要放置许多组件,为了美观,为组件安排在容器中的位置,这就是布局设计.java.awt中定义了多种布局类,每种布局类对应一种布局的策略.常用的有以下布局类: FlowLayout, ...