一开始试着用BFS和DFS写过纯暴力(枚举每个点的最长距离再求最大值),过了一半的测试点(BFS没写出来,DFS过了一半)
接着发现这道题核心是求树的直径,即两次DFS,第一次DFS以任意点为起点,求距离起点最远的点(即树直径的端点,详细图论的证明自行百度),确认树直径的其中一个端点后,用该端点作为起点进行第二次DFS,找到距离该端点最远距离的点,即为直径的另一个端点,两点距离即为直径长度。
接着用等差数列求和公式推导出公式(m为直径长度,S为答案):
S = (mm + 21m)/ 2
直接输出 S即可
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 100010;
struct Edge
{
int id, w;
};
int n, dist[N];
vector<Edge> h[N];
void dfs(int x, int father, int distance)
{
dist[x] = distance;
for(auto node : h[x])
if(node.id != father)
dfs(node.id, x, node.w + distance);
}
int main()
{
cin >> n;
for(int i=1; i<=n-1; i++)
{
int x, y, m;
cin >> x >> y >> m;
h[x].push_back({y, m});
h[y].push_back({x, m});
}
dfs(1, -1, 0);
int u = 1;
for(int i=1; i<=n; i++)
if(dist[i] > dist[u])
u = i;
dfs(u, -1, 0);
int v = u;
for(int i=1; i<=n; i++)
if(dist[i] > dist[v])
v = i;
int mx = dist[v];
cout << (1ll*mx*mx + 21*mx) / 2 << endl;
return 0;
}