树的直径(图论)

Part 1 有根树的直径

对于一棵无根树,我们可以先确定一个结点为根,以确定树的形态。注意,树的形态并不会影响答案,也就是说根是哪个点不重要。

在这里,我们假设树的边权是 1 这种情况(一般情况)

下文所说的树都指有根树。

1. 定义:

一棵树上,集合 T 的元素为任意两个点的距离(是唯一的),集合 T 中最大的数便是树的直径。

2. DP 求法:

先设置两个数组 dp1,dp2. dp1i 表示从 i 出发(向下走)的最长链的长度,dp2i 表示从 i 出发(向下走)的次长链的长度,同时定义 dp1idp2i 是两条不同的链(两个链没有重复的边)

再设置数组 dp. dpi 表示以 i 为根节点的子树的直径。

算法流程:

STEP 1 求出 dp1, dp2

考虑用递归求解:

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 求出 dp

记以 i 为根的子树为 Treei

对于 dpi, 我们需要讨论这两大情况:最后的答案即 Treei 的直径有可能经过结点 i, 或不经过结点 i

直径不经过结点 i 就代表它一定在 Treei 的任一子树里(注意 Treei 的子树和子树之间是互相独立的),所以我们需要枚举在每一个子树的情况。

对于经过结点 i 这一种情况,dpi=max(dpi,dp1i+dp2i)

3. 树的直径的性质

 若一棵树有多个直径,则这些直径都经过其中点。

Part 2 题目——数字转化题解

我们先规定对于任意一种转化关系(x, y), 若 y 为约数和,我们让 y 成为 x 的父亲。

因为对于每个数,都只会有一个约数和,所以每个结点只有一个父亲,所以最后建出来的是树。

然后找出所有子树跑树的直径再取 max 即可。

模板题代码

posted @   Jiayn  阅读(134)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示