P1352 没有上司的舞会 题解

题目传送门

经典树上 DP 问题。

对于该题,我们设状态为 f(i,0/1)

f(i,0) 表示以 i 为根的子树中不选 i 参加的宴会的最大快乐值,f(i,1) 表示以 i 为根的子树中 i 参加的宴会的最大快乐值。

显然,当我们不选 i 时,其所有子节点 jsoni可以选。但我们无法保证 f(j,1)>f(j,0),所以 f(i,0)=(max(f(j,0),f(j,1)))+ri

当我们选 i 时,其所有子节点 jsoni 一定不能选。所以 f(i,1)=f(j,0)

答案即为 max(f(1,0),f(1,1))

转移方程出来了,如何转移呢?由上面的转移方程,我们发现:父节点是由所有子节点转移来的。因此,我们采取 DFS 遍历的方式转移。具体看代码。

#include<bits/stdc++.h>
using namespace std;
const int N = 6e3 + 9;
int n;
struct egde{
	int to,nex;
} e[N << 1];
int head[N],ecnt;
void addegde(int u,int v){
	ecnt++;
	e[ecnt] = (egde){v,head[u]};
	head[u] = ecnt;
}
int r[N];
int dp[N][2];
void dfs(int u,int fa){
	dp[u][0] = 0;dp[u][1] = r[u];
	for(int i = head[u];i;i = e[i].nex){
		int v = e[i].to;
		if(v == fa)
			continue;
		dfs(v,u);
		dp[u][0] += max(dp[v][0],dp[v][1]);
		dp[u][1] += dp[v][0];
	}
}
int main(){
	scanf("%d", &n);
	for(int i = 1;i <= n;i++)
		scanf("%d", &r[i]);
	for(int i = 1;i <= n - 1;i++){
		int u,v;
		scanf("%d%d", &u, &v);
		addegde(u,v);
		addegde(v,u);
	}
	dfs(1,0);
	printf("%d", max(dp[1][0],dp[1][1]));
	return 0;
}
posted @   5t0_0r2  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示