首先要明确什么是树的直径?
树的直径定义如下: 节点对之间距离最远的距离。
可以想象成一棵树的主干。其他的作为分支挂在主干上。
如何计算树的直径?两次BFS。
第一次BFS,从任意一点x开始,沿着x找最远的点A,A就在直径上面。
反证法: 假设直径两点是A和B,从x出发的最远点P不是A或B,那么x-P和A-B一定有一个交叉点y。而y在直径A-B上。因为x-P是x能走的最远距离,那么y-P一定大于y-A和y-B,这样会导致A-y-P会大于A-y-B的路径,那么A-B就不是最远路径了。与我们的假设相反。
第二次BFS从P点出发,最远点就是直径的另一端。
C++代码实现:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using vi = vector<int>;
using vll = vector<ll>;
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define rep(i,a,b) for (int i = (a); i < (b); ++i)
#define per(i,a,b) for (int i = (a); i >= (b); --i)
#define pb push_back
#define eb emplace_back
#define sz(x) ((int)(x).size())
#define fastio do { ios::sync_with_stdio(false); cin.tie(nullptr); } while (0)
#define endl '\n'
#ifdef LOCAL
#define dbg(x) cerr << #x << " = " << (x) << "\n"
#else
#define dbg(x)
#endif
const int INF = 1e9;
const ll LINF = 1e18;
const int MOD = 1e9 + 7;
const int MAXN = 2e5;
const int K = 25;
void solve() {
ll n; std::cin >> n;
if(n == 1){
cout << 0 << endl;
return;
}
vector<vll> g(n);
rep(i, 0, n - 1) {
ll x, y; std::cin >> x >> y;
g[--x].eb(--y);
g[y].eb(x);
}
auto bfs = [&](ll root, vll &dist) {
dist.assign(n, -1);
dist[root] = 0;
queue<ll> q; q.emplace(root);
while(!q.empty()) {
ll u = q.front(); q.pop();
for(const auto &v : g[u]) {
if(dist[v] == -1) {
q.emplace(v);
dist[v] = dist[u] + 1;
}
}
}
};
vll dist(n);
bfs(0, dist);
ll dmax = -INF, vn = -1;
rep(i, 1, n) {
if(dist[i] > dmax) {
dmax = dist[i];
vn = i;
}
}
vll dist2(n);
bfs(vn, dist2);
dmax = -INF, vn = -1;
rep(i, 0, n) {
if(dist2[i] > dmax) {
dmax = dist2[i];
vn = i;
}
}
cout << dmax << endl;
}
int main() {
fastio;
solve();
return 0;
}
如有错误,请及时评判指正!