20250807简单树上问题

引入

树是一种特殊的图,因其看起来像一颗倒挂的树而得名。
树有许多等价的形式化定义,我们这里只取一个:nnn个点n−1n-1n1条边的无向连通图。

这是一颗树

树的直径

定义树上任意两点之间最长的简单路径为树的直径。
一棵树可能有很多直径,如菊花图等。

DFS求法

在没有负边权的情况下,我们一般使用两次DFS求树的直径:
第一次DFS从任意位置出发,找到距离起点最远的点x,xx,xxx是一条直径的端点之一;
第二次DFS从点xxx出发,找到距离点xxx最远的点yyyxxxyyy的路径即为一条直径。

证明&实现

https://oi-wiki.org/graph/tree-diameter/#%E8%BF%87%E7%A8%8B

树形DP

有负边权的情况下,不能使用DFS求法,这时就需要用到树形DP来求解。
任取一个节点作为根节点,对于每个节点xxx,考虑以xxx为根节点的子树中经过xxx的最长的路径,这个路径长度等于xxx向下的最长路径长度+次长路径长度,DFS时分别记录这些信息即可。

实现

void dfs(int u,int fa){d1[u]=d2[u]=0;     //d1是最长路,d2是次长路for(int v:E[u]){if(v==fa)continue;dfs(v,u);int dv=d1[v]+1;if(dv>d1[u]){d2[u]=d1[u];d1[u]=dv; }else if(dv>d2[u]){d2[u]=dv;}}ans=max(ans,d1[u]+d2[u]);
}

树的重心

选择一个合适的根节点,使得根节点的子树能够尽可能的“均匀”,
这个根节点就是树的重心。
如何量化“均匀”呢,我们这里把最大子树节点数认为是“均匀”的程度,
最大子树节点数越小,就越均匀。使得最大子树节点数最小的根节点,就是重心。

性质

●树的重心最多只有两个,若有两个一定相邻。
●以重心作为根节点,根节点的最大子树节点数不会超过n/2n/2n/2
●树上所有点到某个点的距离之和中,到重心的最小。
●把两棵树用一条边连起来,形成的新的树的重心在原来两树重心之间的路径上。
●在一颗树上添加一个叶子节点,重心最多向叶子节点移动一条边。

求法

从任意一点作为根节点出发做DFS,求每个节点的子树节点数,就能知道每个节点作为根节点时的子树大小,向下的子树大小直接统计,向上的子树大小等于n−size[now]n - size[now]nsize[now]

实现

int size[N],mx[N];
void dfs(int u,int fa){for(int v:E[u]){if(v==fa)continue;dfs(v,u);size[u]+=size[v];mx[u]=max(mx[u],size[v]);     // 向下的子树大小}size[u]++;mx[u]=max(mx[u],n-size[u]);    // 向上的子树大小
}

DFS序

树是一种二维的结构,和一维的序列比起来,树的结构更加复杂,我们在思考树上问题的解法时,也常常会先考虑一条(一维序列)上的情况如何求解。

那么有没有一种方法,可以把一颗二维的树,拍扁压缩降维成一个序列呢?我们按照DFS的顺序,记录每个节点第一次被访问到的时间,这就是树的序列化——DFS序(DFN)

性质

DFS有一些神奇的性质,比如一颗子树内的每个节点一定都是连续访问的,
所以一颗子树内的节点的DFS序可以用一个区间表示,
结合我们之前学过的区间查询/区间修改,我们就可以在树上做更多操作。

实现

int dfn[N],size[N],id[N],time;
// dfn[i]表示第i个点的dfs序是dfn[i]
// id[i]表示dfs序为i的点是id[i]
// 第i个点的子树的dfn区间如何表示?
// [dfn[i], dfn[i] + size[i] - 1]
void dfs(int u,int fa){dfn[u]=++time;id[time]=u;for(int v:E[u]){if(v==fa)continue;dfs(v,u);size[u]+=size[v];}size[u]++;
}

最近公共祖先(LCA)

两个点的最近公共祖先,就是两点的公共祖先中距离根节点最远的那个点。

暴力求法

两个点中较深的点跳到它自己的父节点,重复该操作直到两点相遇,此时位置即为LCA。
时间复杂度O(n)O(n)O(n),空间复杂度O(1)O(1)O(1)

倍增求法

我们可以通过倍增预处理出每个点的2k2^k2k级祖先,先把两点移动到相同的高度,如果两点不相同,就可以利用倍增数组logloglog求得最远的不相同的祖先节点,该点的父节点即为LCA。

int fa[20][N];    // 倍增数组,fa[i][x] 表示x号节点的2^i级祖先
int dep[N];
int lca(int a,int b){
//  while(dep[a]<dep[b])b=fa[0][b];if(dep[a]<dep[b])swap(a,b);const int k=dep[a]-dep[b];for(int i=0;i<=19;i++){if(k>>i&1){a=fa[i][a];}}if(a==b)return a;for(int i=19;i>=0;i--){if(fa[i][a]!=fa[i][b]){a=fa[i][a];b=fa[i][b];}}return fa[0][a];
}

DFN上ST表求法

首先处理出dfn,然后在dfn上建st表维护区间内距离根节点最近的节点。
查询lca时,设最小dfn为lll,最大dfn为rrr
只需要查询[l+1,r][l + 1, r][l+1,r]区间内距离根节点最近的节点,该节点的父节点即为lca。

int dfn[N], size[N], id[N], time, dep[N];
int st[20][N];
void init() {for (int i = 1; i <= n; i++) {st[0][i] = id[i];}for (int i = 1, p = 1; i < 20; i++, p <<= 1) {for (int j = 1; j + p * 2 - 1 <= n; j++) {st[i][j] = dep[st[i-1][j]] < dep[st[i-1][j+p]] ?st[i-1][j] : st[i-1][j+p];}}
}
int lca(int a, int b) {if (a == b) return a;int l = dfn[a], r = dfn[b];if (l > r) swap(l, r);
//    [l + 1, r]l++;int len = r - l + 1;int k = lg2[len];if (dep[st[k][l]] < dep[st[k][r-(1<<k)+1]]) {return fa[st[k][l]];} else {return fa[st[k][r-(1<<k)+1]];}
}

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

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

相关文章

诺基亚就4G/5G相关专利起诉吉利对中国汽车及蜂窝模组企业的影响

诺基亚于2025年7月18日向欧洲统一专利法院&#xff08;UPC&#xff09;曼海姆分庭和德国慕尼黑法院提起诉讼&#xff0c;控诉中国吉利控股集团及其极氪、领克、路特斯、Smart等关联品牌在未经许可的情况下使用诺基亚4项蜂窝通信标准必要专利 。涉案专利包括1项覆盖4G/5G的标准必…

Kotlin反射详解

反射是一种机制&#xff0c;它允许我们在运行时检查、修改和操作类或对象的内部结构。反射开启了动态编程的可能性&#xff0c;在开发库、框架或工具等场景中非常有用。Java 中的反射 在 Java 中&#xff0c;反射一直是实现动态编程的重要基石。它允许开发者在不提前知道类名的…

学习嵌入式-IMX6ULL学习——中断

volatile&#xff1a;易变的&#xff0c;防止系统优化对寄存器做处理的时候使用&#xff0c;在进行写1清零操作时&#xff0c;防止该操作被系统优化&#xff1b;一、GIC通用中断控制器1.GIC通用中断控制器GIC接收众多外部中断&#xff0c;然后对其进行处理&#xff0c;最终通过…

HENGSHI SENSE 6.0 功能-AI 查数助手

面向所有AI Agent开放BI和数据分析能力 AI 查数助手 6.0版本中&#xff0c;我们AI助手的优化是比较深入且全面的。从问答效率到集成能力&#xff0c;都得到了大的跃升&#xff0c;是智能问数应用场景的重大升级以及体验的全方位优化。我们优化了 AI 助手执行流程&#xff0c;…

降压型DCDC电源芯片推荐-芯伯乐XBL4001 40V/5A

在电子设备不断追求高性能与低功耗的今天&#xff0c;电源管理芯片的重要性不言而喻。芯伯乐主推的XBLW-XBL4001芯片&#xff0c;凭借其出色的设计与稳定的性能&#xff0c;为电源管理领域带来了一款实用的新选择。一、芯片概述XBLW-XBL4001是一款降压型&#xff08;Buck&#…

uni-app app端安卓和ios如何申请麦克风权限,唤起提醒弹框

代码包含功能如下&#xff1a; 1、判断推送权限是否开启 2、判断定位权限是否开启 3、判断麦克风权限是否开启 4、判断相机权限是否开启 5、判断相册权限是否开启 6、判断通讯录权限是否开启 7、判断日历权限是否开启 8、判断备忘录权限是否开启 9、Android权限查询 10、检查系…

关于 Rust 异步(无栈协程)的相关疑问

这是一个记录问题求助的文章。关于 waker 与运行时的合作方式我肤浅地学习了 Rust 异步底层实现原理&#xff0c;关于 Future、waker 和运行时等。关于 waker 我有三点猜测&#xff1a;waker 是由实现执行器的人提供的在执行器中会调用 epoll_wait&#xff0c;epoll 返回 fd&am…

stm32项目(25)——基于stm32的植物生长箱环境监测系统

1.实现功能 测 环境温湿度、光照强度、土壤湿度、水箱水位 手机APP显示 温度过低-->打开加热板 湿度过低-->打开水泵 土壤湿度低-->开水泵 --->只要有指标低于阈值时 就蜂鸣器报警 光强弱-->补光 水位低-->抽水 OLED屏幕实时显示各种信息 分…

golang 基础案例_02

1.锁有时候我们的代码中可能会存在多个 goroutine 同时操作一个资源&#xff08;临界区&#xff09;的情况&#xff0c;这种情况下就会发生竞态问题&#xff08;数据竞态&#xff09;。(1)、互斥锁&#xff1b;(2)、读写互斥锁&#xff1b;(3)、sync.WaitGroup&#xff1b;(4)、…

C++算法·前缀和

前缀和(Prefix(Prefix(Prefix Sum)Sum)Sum)的定义 前缀和是一种高效处理区间求和问题的算法技巧 其核心思想是通过预处理构建一个前缀和数组 使得后续的区间和查询可以在常数时间O(1)O(1)O(1)内完成 核心概念 定义 给定一个数组a[1...n]a[1...n]a[1...n],其前缀和数组s[1...…

JavaEE 初阶第十七期:文件 IO 的 “管道艺术”(下)

专栏&#xff1a;JavaEE初阶起飞计划 个人主页&#xff1a;手握风云 目录 一、Java文件内容写入 1.1. OutputStream 二、字符流读取和写入 2.1. Reader 2.2. Writer 三、示例练习 3.1. 查找文件功能 一、Java文件内容写入 1.1. OutputStream OutputStream同样只是⼀个抽…

【liunx】web高可用---nginx

NGINX简介Nginx&#xff08;发音为 “engine x”&#xff09;是一款由俄罗斯程序员 Igor Sysoev 开发的 轻量级、高性能的 HTTP 和反向代理服务器&#xff0c;同时也是一个 IMAP/POP3/SMTP 代理服务器。自 2004 年首次发布以来&#xff0c;Nginx 凭借其 高并发处理能力、低内存…

FPGA+护理:跨学科发展的探索(二)

FPGA护理&#xff1a;跨学科发展的探索&#xff08;二&#xff09; 系列文章目录 FPGA护理&#xff1a;跨学科发展的探索&#xff08;一&#xff09; 文章目录FPGA护理&#xff1a;跨学科发展的探索&#xff08;二&#xff09;系列文章目录引言三、FPGA 在精神医学护理中的应用…

localforage的数据仓库、实例、storeName和name的概念和区别

在 localForage 中&#xff0c;数据仓库、实例、storeName 和 name 是核心概念&#xff0c;用于管理底层存储&#xff08;IndexedDB/WebSQL/localStorage&#xff09;。以下是详细解释和区别&#xff1a; 1. 数据仓库 (Database) 定义&#xff1a;指底层的物理数据库&#xff…

使用MAS(Microsoft Activation Scripts)永久获得win10专业版和office全套

文章目录Microsoft Activation Scripts简介下载地址使用方法Microsoft Activation Scripts简介 MAS是Microsoft Activation Scripts缩写。 主要提供如下功能&#xff1a; 使用该脚本可以永久获得win10专业版和office全套&#xff08;可选&#xff09; 下载地址 https://pan…

零 shot 语义+在线闭环:深度学习让机器人学会“主动”

来gongzhonghao【图灵学术计算机论文辅导】&#xff0c;快速拿捏更多计算机SCI/CCF发文资讯&#xff5e;在当下&#xff0c;机器人与深度学习的融合正成为AI领域的核心发展趋势&#xff0c;相关研究在顶会顶刊上热度居高不下。从ICLR到CoRL&#xff0c;诸多前沿成果不断涌现&am…

Nginx学习笔记(三)——在 CentOS 7 中配置阿里云镜像源

&#x1f4da; Nginx学习笔记&#xff08;三&#xff09;——在 CentOS 7 中配置阿里云镜像源 在 CentOS 7 中配置阿里云镜像源可显著提升软件安装和更新的速度&#xff0c;以下是详细操作步骤&#xff1a; &#x1f527; 配置阿里云镜像源步骤 1️⃣ 备份原有源配置 sudo mv /…

WebSocket--简单介绍

一、什么是 WebSocket&#xff1f;定义&#xff1a;WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。作用&#xff1a;实现客户端&#xff08;浏览器&#xff09;和服务器之间的实时、双向通信。优势&#xff1a;连接保持&#xff0c;通信实时性强&#xff08;不像 HT…

【STM32 LWIP配置】STM32H723ZG + Ethernet +LWIP 配置 cubemx

STM32H723ZG LAN8742 Ethernet LWIP 配置 cubemx &#x1f31e;这边记录一下这块mcu 配置以太网的过程&#xff0c;IDE是KEIL MDK&#xff0c;其实就是在下面多次提到的blog的基础上 在scatter file进行配置 首先&#xff0c;如果想要简单一点 直接去cubemx 那边获取相关的例…

EI检索-学术会议 | 人工智能、虚拟现实、可视化

第五届人工智能、虚拟现实与可视化国际学术会议&#xff08;AIVRV 2025&#xff09;定于2025年9月5-7日在中国 成都召开。人工智能正驱动各行业智能化转型&#xff0c;提升效率与质量&#xff1b;虚拟现实技术以其沉浸感重塑教育、娱乐、医疗等领域体验&#xff1b;可视化技术…