Hetao P1307 树的剖分 题解 [ 蓝 ] [ 树形 dp ] [ 贪心 ]

news/2025/1/29 10:55:22/文章来源:https://www.cnblogs.com/zhr0102/p/18692899

树的剖分:很厉害的性质题,代码也很好写。运用到了奇偶性拼凑答案的 trick。

image

image

观察

首先发现一个很重要的条件:一个点的点权只可能是 \(0,1,2\)

这个条件开始我们可能无法用上,于是先想最后的结果应该是怎样的。

显然,我们最后取出的方案一定可以被描述为取下以某个节点为根的子树的一部分。同时,一个深度更大的点,如果能取出这样的一部分,那么先取掉这一部分一定是最优的。为啥呢,这一点和今年那道编辑字符串很像,因为如果我不取这个部分,以成全祖先取自己的部分的话,最后的结果还是 \(1\)。因此取这个部分一定不劣。

因此我们就得到了一个贪心的策略:从深度大的往深度小的选,能选则选,这样一定能保证答案最优

那么怎么计算当前节点能不能恰好取到 \(k\) 呢?这时候我们再来看“一个点的点权只可能是 \(0,1,2\)”这个条件,很容易发现这个很像加工零件那道题分奇偶性讨论的 trick。具体而言,就是对于一个大小大于等于 \(2\) 的树,我们一定可以取下其中的某些叶子,使得整棵树权值的奇偶性不变。理由也很简单,首先 \(0\) 的叶子可以全部先摘掉,然后此时要么有 \(2\) 的点,直接摘下 \(2\) 的点即可。要么就是 \(0,2\) 都没有,只有 \(1\),那么此时叶子结点至少有 \(2\) 个(因为树上至少有一条链),这时我们可以取下这两个 \(1\) 的节点,就能让奇偶性不变的同时减少了。

因此,我们可以算出以 \(i\) 为根节点的子树中,让连通块权值为奇数时连通块的最大权值、让连通块权值为偶数时连通块的最大权值,再判断 \(k\) 对应的奇偶性的最大权值是否大于等于 \(k\) 就能判断能不能取了。

实现上,我们可以定义 \(dp_{i,0}\) 表示连通块权值为偶数时的最大权值,\(dp_{i,1}\) 表示连通块权值为奇数时的最大权值,进行如下转移:

\[dp_{u,0}\gets\max(dp_{u,0},dp_{u,1}+dp_{v,1},dp_{u,0}+dp_{v,0}) \]

\[dp_{u,1}\gets\max(dp_{u,1},dp_{u,1}+dp_{v,0},dp_{u,0}+dp_{v,1}) \]

注意,代码实现时这里不能直接转移,因为先转移哪一个都会导致 dp 值被覆盖,应当先用临时变量记录下转移后 dp 的值,再给 dp 数组赋值。

同时注意取了连通块后将 \(dp_{u,0}=dp_{u,1}=-inf\),切不可赋值为 \(0\),因为此时奇数的 dp 值就不成立了。初始化时也是同理,必须注意。

时间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
int n,k,w[100005],ans=0,dp[100005][2];
vector<int>g[100005];
void dfs(int u,int fa)
{dp[u][w[u]&1]=w[u];dp[u][(w[u]&1)^1]=-0x3f3f3f3f;for(auto v:g[u]){if(v==fa)continue;dfs(v,u);int dp0=max(dp[u][0],max(dp[u][0]+dp[v][0],dp[u][1]+dp[v][1]));int dp1=max(dp[u][1],max(dp[u][0]+dp[v][1],dp[u][1]+dp[v][0]));dp[u][0]=dp0;dp[u][1]=dp1;}if(dp[u][k&1]>=k){ans++;dp[u][0]=dp[u][1]=-0x3f3f3f3f;}
}
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n>>k;for(int i=1;i<=n;i++)cin>>w[i];for(int i=1;i<n;i++){int u,v;cin>>u>>v;g[u].push_back(v);g[v].push_back(u);}dfs(1,0);cout<<ans;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/876368.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常见的7种排序算法(转载)

本文介绍了七种常见的排序算法:冒泡排序、选择排序、插入排序、希尔排序、快速排序、归并排序和堆排序。每种算法通过具体步骤和代码实现进行详细讲解,包括时间复杂度分析。文中提供了丰富的示例代码和图解,帮助读者更好地理解各排序算法的工作原理及应用场景。【版权声明】…

【MySQL】MySQL为什么 不用 Docker部署?

MySQL为什么不推荐使用Docker部署 docker可以从远程仓库拉取镜像然后通过镜像快速的部署应用,非常的方便快捷, 但是 , 为什么 一般公司的 Mysql 不用docker部署,而是部署在 物理机器上呢? 一、DB有状态,不方便扩容1.1 Docker容器的两大类型: 有状态 、无状态的区分1.2 My…

RocketMQ实战—1.订单系统面临的技术挑战

大纲 1.一个订单系统的整体架构、业务流程及负载情况 2.订单系统面临的技术问题一:下订单的同时还要发券、发红包、Push推送等导致性能太差 3.订单系统面临的技术问题二:订单退款时经常流程失败导致无法完成退款 4.订单系统面临的技术问题三:第三方客户系统的对接耦合性太高…

【docker】自建 docker 镜像加速

1. 背景 由于神秘原因,国内用户逐渐无法访问 Docker Hub 仓库。这对于开发者来说是个不小的难题。而这个解决方案是通过赛博菩萨 cloudflare(简称 CF)中转请求,解决访问限制并加速访问。刚好之前分享了如何获取免费域名,今天就来分享一下如何用免费域名在CF部署自己的 doc…

hive--MySQL8错误--ERROR 1410 (42000): You are not allowed to create a user with GRANT

错误展示:解决办法: create user hadoopguide@localhost identified by hadoopguide; grant all privileges on hadoopguide.* to hadoopguide@localhost with grant option; 效果图:错误原因: MySQL 8.0 及以上版本不允许在授予权限时隐式创建用户。所以显式创建用户后再授…

【Linux】Linux一键切换镜像源,告别慢速下载,国内镜像让你飞起来!

简介 本文教你如何通过一键切换 Linux 镜像源,快速提高系统软件包的下载速度,告别“慢”的困扰,轻松提升体验。 项目地址:https://github.com/SuperManito/LinuxMirrors 官方文档:https://linuxmirrors.cn/开头 Linux 系统在安装和更新软件时,经常会遇到速度慢的问题,尤…

day05-面向对象编程:基础语法

Java面向对象:类的基础语法[ 任务列表 ] 1.面向对象快速入门 2.什么是面向对象 3.类的基础语法——构造器 4.类的基础语法——this关键字 5.类的基础语法——封装 6.类的基础语法——javabean 7.类的基础语法——static 8.其他———————————————————————…

【docker】通过Docker一键部署群晖NAS!支持自定义内存和CPU、多磁盘挂载、KVM加速!

声明 文中所涉及的技术、思路和工具仅供以学习交流使用,任何人不得将其用于非法用途以及盈利等目的,否则后果自行承担。如有需要,请购买正版软件。今天给大家介绍一个开源项目,让你能够在Linux或者Window11上通过Docker部署群晖NAS,支持多磁盘挂载、KVM加速等等,让你享受…

渗透测试速成

123123321渗透测试速成 主动信息收集 MSF渗透 python反弹一个交互式shell MySQL基础:登录,增删改查.. 框架识别利用:whatweb 信息收集速通 直接arp-scan -l,快速找到IP地址 然后,nmap -A ip+子网掩码,进行全面扫描 探测目标IP地址: 探测主机:arp-scan -l(推荐) 探测当…

Spring AI 提交 PR 实战指南:避免常见坑

今天,我们将简单地了解如何向 Spring AI 提交 PR(Pull Request)。在这个过程中,有一些常见的坑需要大家注意和避免,特别是在 Git 操作方面。我们会重点关注提交信息的规范,如何进行一次合并提交,以及其他在代码质量和结构上需要遵守的要求。 最后,我们会快速回顾一下与…

第一个java程序,HelloWorld

第一个java程序,HelloWorld创建一个java程序后缀名为java编写代码 public class Hello {public static void main (String[] args) {System.out.println("HelloWorld");} }编译 javac java文件 ,会生成一个class文件运行Java文件,java class文件

[Jest] 整合 webpack 综合练习

这一小节,我们来做一个综合的练习,该练习会整合:typescript webpack jest准备工作 首先创建项目目录,通过 npm init -y 进行初始化。 整个项目我们打算使用 typescript 进行开发,因此需要安装 typescript npm i typescript -D然后通过 npx tsc --init 创建 ts 的配置文件,…