蓝桥杯 2023 省A 颜色平衡树

树上启发式合并是一个巧妙的方法。
 

dsu on tree,可以称为树上启发式合并,是一种巧妙的暴力。用一个全局数组存储结果,对于每棵子树,有以下操作:

先遍历轻儿子,处理完轻儿子后将数组清零(要再遍历一次来清零)
遍历重儿子,遍历完不用清零,再遍历,将轻儿子合并到重儿子上去,其合并结果存储于全局数组
用此时的全局数组来计算父亲
重儿子: 对于一个非叶节点u ,设v 是u 的儿子,且以v 为根的子树包含的节点比以u 的其他儿子为根的子树包含的节点都多,则称v 为u 的重儿子

轻儿子: 对于一个非叶节点u ,在u 的各个儿子中,除了重儿子,都是轻儿子

这题还有个关键就是如何判断是否所有存在的颜色个数相同
有个好思路就是,设立全局变量min和max,表示的是子树u的存在的的颜色的最多数量和最小数量,若min==max,则就是满足条件的子树。


 

#include <iostream>
#include <bits/stdc++.h> // 包含常用的标准库头文件
using namespace std;int n; // 存储节点数量// 结构体定义边
struct edge
{int y, next; // 存储节点编号和下一条边的位置
} e[400002]; // 全局数组,存储边信息int first[200001]; // 存储每个节点的第一条边的位置
// 第一个参数为节点编号,第二个参数为节点的颜色编号
int col[200001];
// 存储每个节点的子树大小和重儿子
int size[200001], mson[200001];
// 存储每个颜色对应的节点数量,以及该数量对应的颜色数量
int t[2][200010], mi, ma;
int ans; // 存储结果// 添加边的函数
void add_edge(int x, int y)
{static int len = 0; // 静态变量,用于记录边的数量e[++len] = {y, first[x]}; // 将边的信息存入数组中first[x] = len; // 更新节点的第一条边的位置为当前边的位置
}// 深度优先搜索,用于计算每个节点的子树大小和重儿子
void dfs0(int x)
{size[x] = 1; // 初始化当前节点的子树大小为1// 遍历当前节点的每一条边for (int i = first[x]; i != 0; i = e[i].next){int y = e[i].y; // 获取当前边连接的节点编号dfs0(y); // 递归调用,计算子树的大小// 更新当前节点的重儿子if (size[y] > size[mson[x]])mson[x] = y;size[x] += size[y]; // 更新当前节点的子树大小}
}// 添加节点颜色数量信息到数组t中
void add(int x)
{t[1][t[0][x]]--; // 将原来颜色数量对应的颜色数量减1t[0][x]++; // 将当前颜色数量加1t[1][t[0][x]]++; // 将新的颜色数量对应的颜色数量加1// 更新颜色数量的最小值和最大值if (t[0][x] < mi)mi = t[0][x];if (t[0][x] > ma)ma = t[0][x];// 如果颜色数量为0,则颜色数量最小值加1if (!t[1][mi])mi++;
}// 删除节点颜色数量信息从数组t中
void del(int x)
{t[1][t[0][x]]--; // 将原来颜色数量对应的颜色数量减1t[0][x]--; // 将当前颜色数量减1t[1][t[0][x]]++; // 将新的颜色数量对应的颜色数量加1// 更新颜色数量的最小值if (t[0][x] && t[0][x] < mi)mi = t[0][x];// 如果颜色数量为0,则颜色数量最大值减1if (!t[1][ma])ma--;
}// 遍历以x为根节点的子树,根据type类型进行颜色数量的操作
void dfs1(int x, int type)
{if (type == 0)del(col[x]); // 删除节点颜色数量信息elseadd(col[x]); // 添加节点颜色数量信息// 遍历当前节点的每一个子节点for (int i = first[x]; i; i = e[i].next){int y = e[i].y; // 获取当前边连接的节点编号dfs1(y, type); // 递归调用,处理子节点的信息}
}// 遍历以x为根节点的子树,统计颜色数量相等的子树数量
void dfs2(int x)
{// 遍历当前节点的每一个子节点for (int i = first[x]; i; i = e[i].next){int y = e[i].y; // 获取当前边连接的节点编号// 如果当前节点是重儿子,则跳过if (y == mson[x])continue;dfs2(y); // 递归调用,处理非重儿子的子树dfs1(y, 0); // 处理非重儿子的节点颜色数量信息}// 如果存在重儿子,则处理重儿子的子树if (mson[x])dfs2(mson[x]);// 遍历当前节点的每一个子节点for (int i = first[x]; i; i = e[i].next){int y = e[i].y; // 获取当前边连接的节点编号// 如果当前节点是重儿子,则跳过if (y == mson[x])continue;dfs1(y, 1); // 处理非重儿子的节点颜色数量信息}add(col[x]); // 添加当前节点的颜色数量信息// 如果颜色数量最小值等于颜色数量最大值,说明当前子树中的颜色数量相等if (mi == ma)ans++;
}int main()
{cin >> n; // 输入节点数量int y; // 存储父节点编号for (int i = 1; i <= n; i++){cin >> col[i] >> y; // 输入节点颜色和父节点编号add_edge(y, i); // 添加边信息}dfs0(1); // 计算每个节点的子树大小和重儿子mi = 1; // 初始化颜色数量的最小值为1dfs2(1); // 遍历树的根节点,并统计颜色数量相等的子树数量cout << ans; // 输出结果return 0;
}

进一步注释:
 

len配合first数组,可以记录边的序号。

edge 结构体定义了树的边的信息,其中 ynext 分别代表了以下含义:

  • y:表示当前边所连接的节点的编号。在树的边结构中,每条边连接两个节点,y 就是其中一个节点的编号,表示了这条边连接到了哪个节点。

  • next:表示当前节点 x 的下一条邻接边在边数组中的位置。因为这是一个邻接表的表示方式,所以 next 记录了节点 x 的下一条邻接边在边数组中的位置,以便能够快速地遍历节点 x 的所有邻接边。

t[2][200001]:
       第一行 (t[0][...]) 用于记录每种颜色出现的次数。
       第二行 (t[1][...]) 用于记录不同出现次数的颜色数目。

具体地,t[0][x] 表示颜色 x 出现的次数,而 t[1][y] 表示出现 y 次的不同颜色的数目。通过这个数组,可以实现对每种颜色的统计。

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

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

相关文章

网络七层模型之数据链路层:理解网络通信的架构(二)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Linux相关命令(1)

1、找出文件夹下包含 “aaa” 同时不包含 “bbb”的文件&#xff0c;然后把他们重新生成一下。要求只能用一行命令。 find ./ -type f -name "*aaa*" ! -name "*bbb*" -exec touch {} \;文件系统操作命令 df&#xff1a;列出文件系统的整体磁盘使用情况 …

小孔平板应力集中问题matlab有限元编程【源码+PPT讲义】|三节点三角形单元|平面单元|稀疏矩阵 |Comsol网格

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

样本投递技术

投递技术 APT 组织主要以邮件作为投递载体&#xff0c;邮件的标题、正文和附件都可能携带恶意代码。主要的方式是附件是漏洞文档、附件是二进制可执行程序和正文中包含指向恶意网站的超链接这三种。 APT攻击的载荷类型&#xff1a; 文档类&#xff1a;主要是office文档、pdf文…

数组——LEETCODE的第35题(二分法与lower_bound函数)

数组——LEETCODE的第35题&#xff08;二分法与lower_bound函数&#xff09; 本文主要是根据leetcode 35题所写的关于数组的相关内容&#xff0c;主要包括&#xff1a; 数组的的特性leetcode第35题二分法的解题lower_bound函数的使用 文章目录 数组——LEETCODE的第35题&#x…

面试题(一)

目录 1.JDK、JRE、JVM之间的区别 2.hashcode()和equals()的区别 3.String、StringBuffer、StringBuilder的区别 4.泛型中extends和super的区别 5.和equals()的区别 6.重写和重载的区别 7.List和Set的区别 8.ArrayList和LinkedList区别 9.谈谈ConcurrentHashMap的原理 …

LangChain核心模块 Retrieval——文档加载器

Retrieval ​ 许多LLM申请需要用户的特定数据&#xff0c;这些数据不属于模型训练集的一部分&#xff0c;实现这一目标的主要方法是RAG(检索增强生成)&#xff0c;在这个过程中&#xff0c;将检索外部数据&#xff0c;然后在执行生成步骤时将其传递给LLM。 ​ LangChain 提供…

Unsafe的CAS操作及线程park与unpark

如下是一个参照AQS进行的一个加锁及解锁的简单实现&#xff1a; 多线程并发进行同步业务操作&#xff1b;加锁&#xff1a;尝试进行cas 0->1操作&#xff1b;如果加锁成功则进行业务处理&#xff0c;然后进行锁释放 1->0&#xff0c;然后将列头的线程进行唤醒&#xff1…

GDAL中的地理坐标系、投影坐标系及其相互转换

目录 地理坐标系 国内常用地理坐标系 投影坐标系 国内常用投影坐标系&#xff08;不推荐使用&#xff09; 坐标转换 地理坐标转为投影坐标 投影坐标转为地理坐标 地理坐标系 原理参考这篇文章&#xff1a;地理坐标系与投影坐标系区别与联系 https://yunxingluoyun.blog.…

webserver如何从零开始?

我们要做一个项目&#xff0c;过程是怎么样的呢&#xff1f;git clone ...部署&#xff0c;测试&#xff0c;然后开始写么&#xff0c;这样你大概率会“猪脑过载”&#xff0c;对一个项目的每个部分都没有清晰认识&#xff0c;能写出什么来&#xff1f;写之前当然需要测试每个功…

Linux网络协议栈从应用层到内核层③

文章目录 1、write源码剖析2、vfs层进行数据传输3、socket层进行数据传输4、tcp层进行数据传输5、ip层进行数据传输6、网络设备层进行数据传输7、网卡驱动层进行数据传输8、数据传输的整个流程 1、write源码剖析 系统调用原型 ssize_t write(int fildes, const void *buf, si…

Linux 在线yum安装: PostgreSQL 15.6数据库

Linux 在线yum安装&#xff1a; PostgreSQL 15.6数据库 1、PostgreSQL数据库简介2、在线安装PostgreSQL15.63、配置 PostgreSQL的环境变量4、使用默认用户登录PostgreSQL5、配置 PostgreSQL 允许远程登录6、修改 PostgreSQL 默认端口7、创建数据库和表、远程用户zyl8、pgAdmin远…

MATLAB环境下基于离散小波变换和主成分平均的医学图像融合方法

随着计算机技术和生物影像工程的日趋成熟&#xff0c;医学图像为医疗诊断提供的信息越来越丰富。目前&#xff0c;由于医学成像的设备种类繁多&#xff0c;导致医生获得的图像信息差异较大。如何把这些信息进行整合供医生使用成为当务之急。基于此&#xff0c;医学图像融合技术…

vue3+vite配置环境变量

1、创建环境变量文件&#xff1a;首先在vue3项目根目录创建.env.development 和 .env.prodution两个文件&#xff0c;分别为开发和生产环境&#xff08;必须.env.开头&#xff0c;需要额外环境&#xff0c;配置自定义的文件名称即可&#xff09; 2、在环境变量文件分别写对应…

Android内存优化项目经验分享 兼顾效率与性能

背景 项目上线一段时间后,回顾重要页面 保证更好用户体验及生产效率&#xff0c;做了内存优化和下载导出优化&#xff0c;具体效果如最后的一节的表格所示。 下面针对拍摄流程的两个页面 预览页 导出页优化实例进行介绍&#xff1a; 一.拍摄前预览页面优化 预览效果问题 存在…

试试前端自动化测试(基础篇)

众所周知的原因&#xff0c;前端作为一种特殊的 GUI 软件&#xff0c;做自动化测试困难重重。在快速迭代&#xff0c;UI 变动大的业务中&#xff0c;自动化测试想要落地更是男上加男 &#x1f436;。 近期的学习过程中&#xff0c;翻阅了众多前端自动化测试相关的文章&#xf…

【3D reconstruction 学习笔记】

三维重建 3D reconstruction 1. 相机几何针孔相机摄像机几何 2. 相机标定线性方程组的解齐次线性方程组的解非线性方程组的最小二乘解透镜相机标定带畸变的相机标定 3. 单视图重建2D平面上的变换3D空间上的变换单视测量无穷远点 无穷远线 无穷远平面影消点 影消线单视重构 4. 三…

天艺制盖邀您参观2024第七届世界燕窝及天然滋补品博览会

2024第七届世界燕窝及天然滋补品博览会 2024年8月7-9日| 上海新国际博览中心 上海燕博会 世界燕窝及天然滋补品展览会暨世界滋补产业生态发展大会&#xff08;简称上海燕博会&#xff09;&#xff0c;2017年创办于中国上海&#xff0c;是一年一度的世界燕窝滋补品行业盛会。…

运放PSRR与开关电源纹波分析的实际案例分享!

本文来自看海原创视频教程&#xff1a;《运放秘籍》运算放大器基础精讲及应用第一部*开天 微信公众号&#xff1a;工程师看海 【淘宝】https://m.tb.cn/h.5PAjLi7?tkvmMLW43KO7q CZ3457 「运放秘籍_运算放大器Multisim仿真视频教程第一部开天_工程师看海」 点击链接直接打开 …

k8s入门到实战(一)—— kubernetes概述

k8s 概述 k8s github地址&#xff1a;https://github.com/kubernetes/kubernetes 官方文档&#xff1a;https://kubernetes.io/zh-cn/docs/home/ k8s&#xff0c;全程是 kubernetes&#xff0c;这个名字源于希腊语&#xff0c;意为"舵手"或"飞行员” k8s 这…