树上dp-没有上司的舞会

树上dp-没有上司的舞会

题目来自算法竞赛进阶指南。

​​​​Alt
可以看作一棵树,每个节点都有权重;且选了父节点就不能选子节点,求最大值。

可以 f [ u ] [ 0 ] f[u][0] f[u][0] 表示节点 u u u 不被选择的情况下,由 u u u 作为父节点的完整子树(包括 u u u)可达到的最大值,用 f [ u ] [ 1 ] f[u][1] f[u][1] 表示节点u被选择时子树可达到的最大值

单独研究一个父节点和其引申出的所有子节点,如图:
在这里插入图片描述
第一种情况,选择了父节点 fa \text{fa} fa;那么它的所有子节点 S i S_i Si依题意都不能被选择。故 f [ fa ] [ 1 ] = ∑ i f [ S i ] [ 0 ] ; f[\text{fa}][1]=\sum_i f[S_i][0]; f[fa][1]=if[Si][0];第二种情况,不选择父节点,那么其子节点就没有任何约束。对每个子节点,都需要选择最好的方案(选这个子节点收益最大还是不选的收益最大);因此 f [ fa ] [ 0 ] = ∑ i max ( f [ S i ] [ 0 ] , f [ S i ] [ 1 ] ) ; f[\text{fa}][0]=\sum_i \text{max}(f[S_i][0],f[S_i][1]); f[fa][0]=imax(f[Si][0],f[Si][1]);在实际程序中,首先使用vector用来储存树的结构;其次使用 d f s dfs dfs 来找到以任意节点为父节点所引申的子树的最大值(包括节点)。而在每次 d f s dfs dfs 结束后,最后使用后序 d p dp dp 来更新父节点 u u u 的值。

关键代码片段:

void dfs(int u)
{
	f[u][1]=w[u]; //选的情况先加上父节点权重
	for(int i=0;i<son[u].size;i++)
	{
		int y=son[u][i]; //取出一个子节点
		dfs(y); //搜索以这个子节点为父节点的子树大小
		f[u][1]+=f[y][0], f[u][0]+=max(f[y][0],f[y][1]); //用搜索结果更新父节点的值
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值