树中所有简单路径的最大值即为树的直径,可以通过两次 DFS 或者树形 DP 在 时间内求解。
证明 假设结点 和 之间唯一的简单路径为树的直径, 表示结点 和之间的唯一的简单路径的长度。若该最远点 不是树的直径的一个端点,则对于当前根结点 来说:
与为直径而 不是直径的端点矛盾。
综上可知,一定是树的直径的一个端点。 推论:树中任意结点的最远点要么是,要么是()为树的直径)。 证明同上,略。
子树 的高度等于
其中,取遍 的所有子树,和即对应子树的高度和次高度。
【注】以下模板均是基于无权树求树的直径,有权树只需在前向星中记录一下边权,然后更新结点高度/深度不是 + 1 而是 + 对应边权即可。
#include <bits/stdc++.h>
using namespace std;
#ifndef _DIAMETEROFTREE_
#define _DIAMETEROFTREE_
#define ll int
#define MAXN 10005
// 树的直径
struct DiameterOfTree{
// 前向星存边
ll cnt; // 动态开点
ll head[MAXN]; // 第一条出边
struct Edge{
ll to; // 边的终点
ll next; // 下一条边
}e[MAXN<<1]; // 存取双向边
// 初始化前向星
void init() {
cnt = 0;
memset(head, -1, sizeof(head));
}
// 添加双向边
void addEdge(ll u, ll v) {
// 存取双向边
e[cnt].next = head[u];
e[cnt].to = v;
head[u] = cnt++;
e[cnt].next = head[v];
e[cnt].to = u;
head[v] = cnt++;
}
// DFS 求深度最大的结点
ll ans; // 最大深度结点
ll vis[MAXN]; // 标记数组
ll depth[MAXN]; // 深度数组
void dfs(ll u) {
vis[u] = 1;
for(ll i = head[u]; i != -1; i = e[i].next) {
ll v = e[i].to;
if(!vis[v]) {
depth[v] = depth[u] + 1;
if(depth[v] > depth[ans]) {
ans = v;
}
dfs(v);
}
}
}
// 求解树的直径
ll getDiameter(ll u) {
// 第一遍 DFS
ans = u;
memset(vis, 0, sizeof(vis));
memset(depth, 0, sizeof(depth));
dfs(u);
// 第二边 DFS
memset(vis, 0, sizeof(vis));
memset(depth, 0, sizeof(depth));
dfs(ans);
return depth[ans];
}
};
#endif
#include <bits/stdc++.h>
using namespace std;
#ifndef _DIAMETEROFTREE_
#define _DIAMETEROFTREE_
#define ll int
#define MAXN 10005
// 树的直径
struct DiameterOfTree{
// 前向星存边
ll cnt; // 动态开点
ll head[MAXN]; // 第一条出边
struct Edge{
ll to; // 边的终点
ll next; // 下一条边
}e[MAXN<<1]; // 存取双向边
// 初始化前向星
void init() {
cnt = 0;
memset(head, -1, sizeof(head));
}
// 添加双向边
void addEdge(ll u, ll v) {
// 存取双向边
e[cnt].next = head[u];
e[cnt].to = v;
head[u] = cnt++;
e[cnt].next = head[v];
e[cnt].to = u;
head[v] = cnt++;
}
// DFS 树形 dp
ll diameter; // 树的直径
ll vis[MAXN]; // 标记数组
ll dfs(ll u) {
vis[u] = 1;
ll h1 = 0, h2 = 0;
for(ll i = head[u]; i != -1; i = e[i].next) {
ll v = e[i].to;
if(!vis[v]) {
ll h = dfs(v) + 1;
if(h > h1) {
h2 = h1;
h1 = h;
} else if(h > h2) {
h2 = h;
}
}
}
diameter = max(diameter, h1+h2);
return h1;
}
// 求解树的直径
ll getDiameter(ll u) {
diameter = 0;
memset(vis, 0, sizeof(vis));
dfs(u);
return diameter;
}
};
#endif
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有