四、树的直径(diameter)
树上一条最短路径
找到一条直径 u - v
直径的端点一定是叶子
任取一点a;算出每个点到a的距离
(考虑以a为根的有根树)
设离a最远的一个点是b,那么b一定是直径的端点
扫描后每个点到a的距离:
例题:
描述
有一个有 N 个点的树,点从 1 到 N 编号。第 i 条边连接点 Ai 和点 Bi(1≤i≤N−1)。
现在要往树上加一条新边,这样会形成一个回路。求形成的回路的长度可能达到的最大值。这里,一条回路的长度是回路上边的数量。
限制
- 3≤N≤100000
- 1≤Ai<Bi≤N(1≤i≤N−1)
输入描述
N
A1 B1
A2 B2
⋮
AN BN输出描述
输出答案。
样例输入 1
3 1 2 2 3样例输出 1
3样例输入 2
5 1 2 2 3 3 4 3 5样例输出 2
4样例输入 3
10 1 2 1 3 2 4 4 5 4 6 3 7 7 8 8 9 8 10样例输出 3
8样例输入 4
31 1 2 1 3 2 4 2 5 3 6 3 7 4 8 4 9 5 10 5 11 6 12 6 13 7 14 7 15 8 16 8 17 9 18 9 19 10 20 10 21 11 22 11 23 12 24 12 25 13 26 13 27 14 28 14 29 15 30 15 31样例输出 4
9
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
vector<int> g[maxn];
int dist[maxn];
void dfs(int u, int p)
{
for (int v: g[u])
{
if (v != p)
{
dist[v] = dist[u] + 1;
dfs(v, u);
}
}
}
int main()
{
int n;
cin >> n;
for (int i = 1; i < n; i++)
{
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1, 0);
int x = max_element(dist + 1, dist + n + 1) - dist;
dist[x] = 0;
dfs(x, 0);
cout << *max_element(dist + 1, dist + n + 1) + 1;
return 0;
}