没有上司的舞会|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.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的 ...
随机推荐
- Windows 下使用 MinGW 和 CMake 进行开发
CMake 是个非常棒的项目管理工具,这已经是毋庸置疑的. 一些小工具需要在 win 下开发,所以今天探索使用 MinGW 和 CMake 在 win 下的搭配使用.简单做记录. MinGW 使用 Q ...
- 学校公文办公处理系统_基于ASP.NET和Swfupload、FlashPaper2.2、校讯通短信发送的开发
学校新来了一个主管教学的副校长,他对他以前工作学校的公文处理系统表示高度留念,于是乎叫我们也开发一个. 我就参考了那个学校的办公管理系统,发现其实功能也蛮简单的,就是一个文件上传下载的功能,选择用户组 ...
- 001_ASP.NET MVC 实用教程 论坛项目 北盟网校 原创视频教程
下载地址 http://pan.baidu.com/s/1kUJalbp 在线观看地址 http://www.bamn.cn/course/lesson/1 ASP.NET MVC 使用课程,是201 ...
- 基于Ubuntu搭建Seafile专属网盘
系统要求: Ubuntu 16.04.1 LTS 64 位操作系统 安装 Seafile 服务器 安装依赖环境 在 Debian/Ubuntu 系统下,可以使用以下命令安装 MySQL: sudo a ...
- Linux 下hosts文件详解
1.主机名: 无论在局域网还是INTERNET上,每台主机都有一个IP地址,是为了区分此台主机和彼台主机,也就是说IP地址就是主机的门牌号. 公网:IP地址不方便记忆,所以又有了域名.域名只是在公网( ...
- 腾讯QQ会员中心g_tk32算法【C#版】
最近用C#写qq活动辅助类程序,碰到了会员签到的gtk算法不一样,后来网上找了看,发现有php版的(https://www.oschina.net/code/snippet_1378052_48831 ...
- oracle 12c common user与local user
12c的多租户架构,引入CDB和PDB概念,使得用户也分为两种:common用户和local用户. 1.common用户就是数据库的用户,这个用户在root和每个已存在的或以后要创建的PDB都是相同的 ...
- [svc]runinit管理多进程
runinit启动小程序测试 与Supervisord类似的工具包括monit, daemontools和runit. 我还发现个神器,专门针对单容器启动多进程的神器s6: https://githu ...
- Android查询不到电话号码解决方法
貌似联系人有三个数据库,且不同步,另外也有可能是版本问题. 解决方案:https://github.com/codinguser/android_contact_picker 接下来会对其进行一些改造 ...
- 【Linux】Linux基本命令扫盲
[VI使用] 1.在命令行模式 :在vi编辑器中将光标放在函数上, 定位到每行的开头,不进入输入模式,$ 定位到每行的末尾 :[n]dd 剪贴n行,p粘贴 : dG 删除光标后 ...