我的思路是:找到任意直径 p -> q 长度为 d,
然后 从 p dfs 一遍标记所有直径的另一端 qi(正确性是显然的,所有直径的两端都是相齐的)
对 qi 找多点 lca,就是 q 端的必经点 lcaq
对称过来找到 p 端 的必经点 lcap
必经边的长度就是 dep[lcap] + dep[lcaq] - 2 * dep[lca(lcap, lcaq)]
样例过了,但只有 20pts
附:
#include <bits/stdc++.h>
#define re register int
using namespace std;
typedef long long LL;
const int N = 2e5 + 10, logN = 50;
const int inf = 0x3f3f3f3f;
struct Edge
{
int to, w, next;
}e[N << 1];
int top, h[N];
int f[N][logN], dep[N], sum[N];
int n, p, q, dfn[N], idx;
LL len, maxs;
bool st[N];
inline void add(int x, int y, int w)
{
e[++ top] = (Edge){y, w, h[x]};
h[x] = top;
}
void dfs(int u, int fa, LL size, int & ver, int type)
{
if (size > maxs)
{
maxs = size;
ver = u;
if (type) len = size;
}
for (re i = h[u]; i; i = e[i].next)
{
int v = e[i].to, w = e[i].w;
if (v == fa) continue;
dfs(v, u, size + w, ver, type);
}
}
void draw(int u, int fa, LL size)
{
if (size == len)
{
st[u] = true;
return;
}
for (re i = h[u]; i; i = e[i].next)
{
int v = e[i].to, w = e[i].w;
if (v == fa) continue;
draw(v, u, size + w);
}
}
void init(int u, int fa)
{
dep[u] = dep[fa] + 1;
f[u][0] = fa;
for (re i = 1; i <= log2(n); i ++)
f[u][i] = f[f[u][i - 1]][i - 1];
for (re i = h[u]; i; i = e[i].next)
{
int v = e[i].to, w = e[i].to;
if (v == fa) continue;
sum[v] = sum[u] + w;
init(v, u);
}
}
inline int lca(int u, int v)
{
if (dep[u] < dep[v]) swap(u, v);
for (re i = log2(n); i >= 0; i --)
if (dep[f[u][i]] >= dep[v]) u = f[u][i];
if (u == v) return u;
for (re i = log2(n); i >= 0; i --)
if (f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
return f[u][0];
}
void get_dfn(int u, int fa)
{
dfn[++ idx] = u;
for (re i = h[u]; i; i = e[i].next)
{
int v = e[i].to;
if (v == fa) continue;
get_dfn(v, u);
}
dfn[++ idx] = u;
}
inline void work()
{
draw(p, 0, 0);
init(1, 0);
get_dfn(1, 0);
// cout << p << ' ' << q << '\n';
// for (re i = 1; i <= n; i ++) cout << i << ' ' << st[i] << '\n';
// for (re i = 1; i <= idx; i ++)
// cout << dfn[i] << ' ';
int minn = inf, maxn = 0, l, r;
for (re i = 1; i <= idx; i ++)
if (st[dfn[i]])
{
if (i < minn) minn = i, l = dfn[i];
if (i > maxn) maxn = i, r = dfn[i];
}
// cout << '\n' << l << ' ' << r << '\n';
int lcap = lca(l, r);
// cout << lcap << '\n';
memset(dep, 0, sizeof(dep));
memset(f, 0, sizeof(f));
memset(sum, 0, sizeof(sum));
memset(st, false, sizeof(st));
minn = inf, maxn = 0;
idx = 0;
draw(q, 0, 0);
init(1, 0);
get_dfn(1, 0);
for (re i = 1; i <= idx; i ++)
if (st[dfn[i]])
{
if (i < minn) minn = i, l = dfn[i];
if (i > maxn) maxn = i, r = dfn[i];
}
int lcaq = lca(l, r);
// cout << lcaq << '\n';
cout << dep[lcap] + dep[lcaq] - 2 * dep[lca(lcap, lcaq)] << '\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n;
for (re i = 1; i < n; i ++)
{
int x, y, w; cin >> x >> y >> w;
add(x, y, w);
add(y, x, w);
}
dfs(1, 0, 0, p, 0);
maxs = 0;
dfs(p, 0, 0, q, 1);
cout << len << '\n';
work();
return 0;
}