首页 > 其他分享 >没有上司的舞会 - 树形动态规划

没有上司的舞会 - 树形动态规划

时间:2023-04-07 22:02:14浏览次数:46  
标签:舞会 上司 int 树形 为根 节点 职员

没有上司的舞会 - 树形动态规划

题意

某大学有 \(n\) 个职员,编号为 \(1\ldots n\)。

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

现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数 \(r_i\),但是呢,如果某个职员的直接上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。

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

输入的第一行是一个整数 \(n\)。

第 \(2\) 到第 \((n + 1)\) 行,每行一个整数,第 \((i+1)\) 行的整数表示 \(i\) 号职员的快乐指数 \(r_i\)。

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

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

样例输入输出

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

算法

树形动态规划 (树形DP)

\(\to\) OI-Wiki

树形 DP,即在树上进行的 DP。由于树固有的递归性质,树形 DP 一般都是递归进行的。

解题思路

对于这道题目,我们首先建树,然后递归处理每一个树上的节点,最后找最大值。

由于这道题目中没有给出明确的根节点的编号,因此我们需要找到这个根节点,而根节点的性质是没有父节点,因此循环判断这个点有没有父亲节点即可。

1. 确定状态

二维状态。

\(f_{u, 0}\) 表示所有从以 \(u\) 为根的子树中选择,并且不包含 \(u\) 点的最大高兴值。

\(f_{u, 1}\) 表示所有从以 \(u\) 为根的子树中选择,并且包含 \(u\) 点的最大高兴值。

2. 划分阶段 & 决策选择

递归处理 \(u\) 点的所有子节点。

对于求 \(f_{u, 0}\)

如果求 \(f_{u, 0}\),则代表不选 \(u\) 这个点,那么 \(u\) 点的所有子节点都可选可不选。所以 \(f_{u, 0} = \sum \max(f_{v, 0}, f_{v, 1})\),其中 \(v\) 是 \(u\) 的所有子节点。

对于求 \(f_{u, 1}\)

如果求 \(f_{u, 1}\),则代表选 \(u\) 这个点,那么 \(u\) 点的所有子节点都不可选。所以 \(f_{u, 1} = r_u + \sum f_{v, 0}\),其中 \(v\) 是 \(u\) 的所有子节点。

3. 求解目标

最终求的是所有人的总情况,也就是跟这棵树的根节点有关。而根节点可选可不选,所以最终答案为 \(\max(f_{root, 1}, f_{root, 0})\)。

代码

#include <iostream>
#include <vector>

using namespace std;

const int N = 6e3 + 10;

int n, l, k, root = 1;
int r[N];
int f[N][2];
/*
f[i][0] 表示所有从以 u 为根的子树中选择,并且不包含 u 点的最大高兴值
f[i][1] 表示所有从以 u 为根的子树中选择,并且包含 u 点的最大高兴值
*/
bool has_father[N];		// 存储每个节点是否都存在父节点,不存在的点为根节点 
vector<int> g[N];		// 邻接表 

void dp(int u){
	// 加上 u 点的高兴值 
	f[u][1] += r[u];
	
	for(auto v : g[u]){	// 枚举 u 的左右子节点 
		dp(v);			// 递归 
		f[u][0] += max(f[v][0], f[v][1]);
		f[u][1] += f[v][0];
	}
}

int main(){
	// 读入 
	scanf("%d", &n);
	
	for(int i=1; i<=n; i++)
		scanf("%d", r + i);
	
	for(int i=1; i<n; i++){
		scanf("%d %d", &l, &k);
		has_father[l] = true;	// 标记 l 点存在父节点 
		g[k].push_back(l);
	}
	
	// 寻找根节点 
	while(has_father[root])
		root++;
	
	dp(root); 	// 树形 DP 
	
	
	printf("%d", max(f[root][1], f[root][0]));	// 找最大值输出 
	
	return 0;
}

标签:舞会,上司,int,树形,为根,节点,职员
From: https://www.cnblogs.com/2huk/p/17297496.html

相关文章

  • 树形dp
    https://atcoder.jp/contests/abc259/tasks/abc259_f树形dp(最简单的那种类型,但是题目的方法还是很巧妙的)易知:负权边可以忽略思路定义定义f[i][0]表示以i为根的子树尽量用到d[i]-1条边的最大可能(留一条边给父节点联通用)f[i][1]表示以i为根的子树尽量用到d[i]条边的最大可......
  • Javascript中扁平化数据结构与JSON树形结构转换详解
    Javascript中扁平化数据结构与JSON树形结构转换详解原文链接:https://www.jb51.net/article/247525.htm+目录一.先说简单的树形结构数扁平化处理二.再讲将扁平化数据结构转JSON树状形结构扩充一个知识点:forin与forof的区别:总结不废话,直接开干一.先说简单的树形结构数......
  • Gorm 实现无限树形菜单
    原文链接:https://www.zhoubotong.site/post/91.html通常树形菜单的实现基本就是递归调用,大部分场景毕竟这种数据不多,性能倒是并不突出,下面给个demo,有兴趣的朋友可以看看:新建一个city表:CREATETABLE`city`(`id`intNOTNULLAUTO_INCREMENT,`pid`intNOTNULLDEFA......
  • js 递归遍历树形结构数据,返回新的数组
    工作中,我们经常会遇到这样的情况:后端返回的数组,只需要取name、value生成新的数组,或者是将某个属性名修改,生成新的数组。递归是一种常见的解决问题的方法,即把问题逐渐简单化。“递归”的基本思想是:自己调用自己。实例如下handleDg(arrs,that){arrs.map((item,index)......
  • HDU 2196 Computer(树形DP) 入门模板
    ComputerTimeLimit:1000/1000MS(Java/Others)    MemoryLimit:32768/32768K(Java/Others)TotalSubmission(s):34313    AcceptedSubmission(s):5345 ProblemDescriptionAschoolboughtthefirstcomputersometimeago(sothiscomputer'sidis1).D......
  • element树形复选框实现一级菜单单选
      <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=d......
  • 树形DP——小红树
    题目描述小红拿到了一棵树,每个节点被染成了红色或者蓝色。小红定义每条边的权值为:删除这条边时,形成的两个子树的同色连通块数量之差的绝对值。小红想知道,所有边的权值之和是多少?输入描述第一行输入一个正整数n,代表节点的数量。第二行输入一个长度为n且仅由'R'和'B'两种字......
  • 项目一众筹网05_02_[树形开发]菜单管理、API文档发布到web服务器、配置文件里面修改to
    系列文章目录文章目录系列文章目录08-页面显示树形结构-前端-使用真实数据09-准备zTree的API文档(因为现在没有图标)==API文档发布到web服务器上去==配置文件里面修改tomcat的默认端口号(只需改动3个地方)10-前端-显示图标-分析思路(-页面显示树形结构)11-前端-显示图标-代码实现(-页面......
  • 项目一众筹网05_01_[树形结构开发]菜单维护-树形结构基础知识、自关联、zTree的介绍和
    树形结构开发]菜单维护文章目录树形结构开发]菜单维护01-菜单维护-树形结构基础知识-上==在数据库中怎么去表示树形关系====其实这就是自关联====我们怎么识别根节点==02-菜单维护-树形结构基础知识-下03-页面显示树形结构-后端-逆向工程==开发的细节:如何避免空指针异常:初始化==04-......
  • 【做题笔记】树形 dp
    1.luoguP2016战略游戏1.1Solve设计状态\(dp[i][0/1]\)表示在\(i\)子树内,放/不放第\(i\)个节点使其合法所需的最少的士兵数目。则有:不选\(i\)节点,则\(i\)的儿子必须选;选\(i\)节点,则\(i\)的儿子可选可不选;因此,转移方程为:$dp[i][0]=\sumdp[son[i]][1......