当前位置: 首页 > news >正文

没有上司的舞会(C++,树形DP)

题目描述

某大学有 nnn 个职员,编号为 1…n1\ldots n1n

他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。

现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数 rir_iri

但是呢,如果某个职员的直接上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。

所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。

输入格式

输入的第一行是一个整数 nnn

222 到第 (n+1)(n + 1)(n+1) 行,每行一个整数,第 (i+1)(i+1)(i+1) 行的整数表示 iii 号职员的快乐指数 rir_iri

(n+2)(n + 2)(n+2) 到第 2n2n2n 行,每行输入一对整数 l,kl, kl,k,代表 kkklll 的直接上司。

输出格式

输出一行一个整数代表最大的快乐指数。

样例 #1

样例输入 #1

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5

样例输出 #1

5

提示

数据规模与约定

对于 100%100\%100% 的数据,保证 1≤n≤6×1031\leq n \leq 6 \times 10^31n6×103−128≤ri≤127-128 \leq r_i\leq 127128ri1271≤l,k≤n1 \leq l, k \leq n1l,kn,且给出的关系一定是一棵树。

解题思路:

首先,注意题中说的是“如果某个职员的直接上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。”

也就是说间接上司来不来是无所谓的

接下来讲解本题的解题思路

这道题可以算是树形DP的入门级题目了

树形DP,就是在树形结构中采用动态规划
(说了但好像什么都没说)

常规思路就是自顶向下递推,确定叶子节点后,逐级回归更新父节点

那么这道题为什么采用树形DP呢?

首先题目中给出的是一棵树

其次,我们想要知道舞会的最大快乐指数,除了遍历每一种可能外好像别无选择

那么降低时间复杂度就要想到DP,在本题中也就是树形DP

思路很简单,每个职员只有两种状态:来、不来

我们用dp[now][1]表示来,dp[now][0]表示不来

那么有

//树形DP
void dfs(int now) {//参加dp[now][1] = happy[now];//参加,初始化为自己的快乐指数//不参加for (int i = head[now]; i != -1; i = edges[i].next) {//遍历子节点int v = edges[i].v;dfs(v);//返回后更新dp[now][0] += max(dp[v][0], dp[v][1]);//不参加,需要累加子节点来的情况dp[now][1] += dp[v][0];//参加,需要累加子节点不来的情况}
}

最后,AC代码如下

#include <iostream>
#include <string.h>
using namespace std;
const int max_n = 6e3;
const int min_r = -128;
const int max_r = 127;int n, u, v;
int happy[max_n + 1];
int in[max_n + 1];
//链式前向星
struct edge { int v, next; }edges[max_n + 1];
int head[max_n + 1];
int tot = -1;
//树形DP
long long dp[max_n + 1][2];//存边
void add_edge(int u, int v) {edges[++tot] = { v,head[u] }; head[u] = tot;
}//树形DP
void dfs(int now) {//参加dp[now][1] = happy[now];//参加,初始化为自己的快乐指数//不参加for (int i = head[now]; i != -1; i = edges[i].next) {//遍历子节点int v = edges[i].v;dfs(v);//返回后更新dp[now][0] += max(dp[v][0], dp[v][1]);//不参加,需要累加子节点来的情况dp[now][1] += dp[v][0];//参加,需要累加子节点不来的情况}
}int main() {memset(head + 1, -1, sizeof(int) * max_n);cin >> n;for (int i = 1; i <= n; i++) cin >> happy[i];for (int i = 1; i < n; i++) {//存图cin >> u >> v;add_edge(v, u);//反向存边,自顶向下in[u]++;}for (int i = 1; i <= n; i++)if (!in[i]) {//从根节点开始dfs(i);cout << max(dp[i][0], dp[i][1]) << endl;break;}return 0;
}
http://www.lryc.cn/news/21364.html

相关文章:

  • 【java基础】static和final关键字的作用及其用法详解
  • #集成学习#:bagging、boosting、stacking和blending
  • NCRE计算机等级考试Python真题(一)
  • C#协变逆变
  • 算法设计与分析期末考试复习(四)
  • qsort函数排序数据 and 模拟实现qosrt函数(详解)
  • Mysql视图,存储过程,触发器,函数以及Mysql架构
  • 什么是线程死锁?如何解决死锁问题
  • C语言几种判断语句简述
  • 【python学习笔记】:SQL常用脚本(二)
  • 【Linux】进程地址空间
  • Qt音视频开发17-vlc内核回调拿图片进行绘制
  • 安装配置DHCP
  • MarkDown中写UML图的方法
  • Axure8设计—动态仪表盘
  • 【C++】类和对象的六个默认成员函数
  • 4、算法MATLAB---认识矩阵
  • vue3+rust个人博客建站日记2-确定需求
  • Linux安装云原生网关Kong/KongA
  • Vue学习笔记(2)
  • 2023年三月份图形化四级打卡试题
  • Python操作Excel
  • Codeforces Round #853 (Div. 2) C. Serval and Toxel‘s Arrays【统计次数,算贡献】
  • 微信小程序-1:比较两数的大小
  • 数据结构——树
  • 【华为OD机试模拟题】用 C++ 实现 - 找到它(2023.Q1)
  • python中yield的使用
  • GO进阶(4) 深入Go的内存管理
  • 【C++】类与对象理解和学习(下)
  • 【Neo4j】Spring Data Neo4j APi阅读随笔