树的直径
树的直径即为一棵树上的最长链。一般分为有负权图和无负权图来考虑。
无负权
只需做两次dfs。
第一次是搜索出从任一点出发到达的最远的点P,那么这个点就一定在最长链上(请自证)。
第二次搜索从点P出发到达的最远的点Q,那么最长链即为P与Q的距离。
题目:B4016 树的直径
代码:
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, lth[N], ans, mx, pas;
vector <int> e[N];
void dfs(int u, int fa)
{
lth[u] = lth[fa] + 1;
if(lth[u] > mx) mx = lth[u], pas = u;
for(int i = 0; i < e[u].size(); i ++)
{
if(e[u][i] == fa) continue;
dfs(e[u][i], u);
}
}
int main()
{
cin >> n;
int u, v;
for(int i = 1; i < n; i ++)
{
scanf("%d %d", &u, &v);
e[u].push_back(v), e[v].push_back(u);
}
dfs(1, 0);
mx = 0;
memset(lth, 0, sizeof(lth));
dfs(pas, 0);
ans = mx;
cout << ans - 1 << endl;
return 0;
}
有负权
前面的做法显然不能解决这类问题,那么我们考虑树形dp(其实也是搜索)
接下来介绍两种做法,都要先确定根节点,以下的链都是以某点为子树的根,到达子节点的长度。
- 记录每个点出发的最长链和次长链(链没有公共边)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
int n, d1[N], d2[N], d;
vector <int> E[N], W[N];
void dfs(int u, int fa)
{
for(int i = 0; i < E[u].size(); i ++)
{
int v = E[u][i], val = W[u][i];
if(v == fa) continue;
dfs(v, u);
int t = d1[v] + val;
if(t > d1[u]) d2[u] = d1[u], d1[u] = t;
else if(t > d2[u]) d2[u] = t;
d = max(d, d1[u] + d2[u]);
}
}
int main()
{
cin >> n;
for(int i = 1; i < n; i ++)
{
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
E[u].push_back(v), E[v].push_back(u);
W[u].push_back(w), W[v].push_back(w);
}
dfs(1, 0);
printf("%d\n", d);
return 0;
}
- 直接记录最长链,答案就是最长链与该节点出发的另一链的和(本质就是次长链,但是写起来比较方便)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
int n, d, dp[N];
vector <int> E[N], W[N];
void dfs(int u, int fa)
{
for(int i = 0; i < E[u].size(); i ++)
{
int v = E[u][i], val = W[u][i];
if(v == fa) continue;
dfs(v, u);
d = max(d, dp[u] + dp[v] + val);
dp[u] = max(dp[u], dp[v] + val);
}
}
int main()
{
cin >> n;
for(int i = 1; i < n; i ++)
{
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
E[u].push_back(v), E[v].push_back(u);
W[u].push_back(w), W[v].push_back(w);
}
dfs(1, 0);
printf("%d\n", d);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效