树的直径(图论)
Part 1 有根树的直径
对于一棵无根树,我们可以先确定一个结点为根,以确定树的形态。注意,树的形态并不会影响答案,也就是说根是哪个点不重要。
在这里,我们假设树的边权是 这种情况(一般情况)
下文所说的树都指有根树。
1. 定义:
一棵树上,集合 的元素为任意两个点的距离(是唯一的),集合 中最大的数便是树的直径。
2. DP 求法:
先设置两个数组 . 表示从 出发(向下走)的最长链的长度, 表示从 出发(向下走)的次长链的长度,同时定义 和 是两条不同的链(两个链没有重复的边)。
再设置数组 . 表示以 为根节点的子树的直径。
算法流程:
STEP 1 求出 , :
考虑用递归求解:
void dfs(int x){ //dfs(x) 可求出 dp1[x] 与 dp2[x]
循环考察结点 x 的所有孩子节点(毕竟最后的次长/最长链一定会包含一条x的出边)
对于每一个孩子结点 u:
1° dp1[u] + 1 < dp2[x]: dp1[x] 和 dp2[x] 都不用更新
2° dp2[x] < dp1[u] + 1 < dp1[x]: dp1[x] 不用更新, dp2[x] = dp1[u] + 1
3° dp1[u] + 1 >= dp1[x]: dp2[x]=dp1[x], dp1[x] = dp1[u] + 1
}
STEP 2 求出 :
记以 为根的子树为
对于 , 我们需要讨论这两大情况:最后的答案即 的直径有可能经过结点 , 或不经过结点
直径不经过结点 就代表它一定在 的任一子树里(注意 的子树和子树之间是互相独立的),所以我们需要枚举在每一个子树的情况。
对于经过结点 这一种情况,
3. 树的直径的性质
若一棵树有多个直径,则这些直径都经过其中点。
Part 2 题目——数字转化题解
我们先规定对于任意一种转化关系(x, y), 若 为约数和,我们让 成为 的父亲。
因为对于每个数,都只会有一个约数和,所以每个结点只有一个父亲,所以最后建出来的是树。
然后找出所有子树跑树的直径再取 max 即可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)