原题传送门
本来想的一个
O
(
n
2
)
O(n^2)
O(n2)的暴力
枚举
C
C
C,把它记为根,在
d
f
s
dfs
dfs枚举
l
c
a
(
A
,
B
)
lca(A,B)
lca(A,B)
求出
f
i
r
u
,
s
e
c
u
fir_u,sec_u
firu,secu表示以
u
u
u为根的子树中最长链,次长链
再记
d
u
d_u
du为深度,那么对于一个
(
C
,
l
c
a
(
A
,
B
)
)
(C,lca(A,B))
(C,lca(A,B))的答案是
f
i
r
u
+
2
s
e
c
u
+
d
u
fir_u+2sec_u+d_u
firu+2secu+du
其实可以只枚举
l
c
a
(
A
,
B
)
lca(A,B)
lca(A,B)记为
D
D
D好了,想要知道在
f
i
r
D
,
s
e
c
D
fir_D,sec_D
firD,secD已经有的情况下,最优的
C
C
C在哪
对于每个点求出
f
i
r
u
,
s
e
c
u
,
t
h
i
u
fir_u,sec_u,thi_u
firu,secu,thiu,前三长的链,以及
i
d
f
i
r
u
idfir_u
idfiru最长链对应的儿子编号
然后再
d
f
s
dfs
dfs,如果走到最长链里面,即
v
=
i
d
f
i
r
u
v=idfir_u
v=idfiru,则顺便传下去
s
e
c
u
+
l
sec_u+l
secu+l
否则传下去
f
i
r
u
+
l
fir_u+l
firu+l
对于每个点
u
u
u,我们知道了
f
i
r
u
,
s
e
c
u
,
t
h
i
u
fir_u,sec_u,thi_u
firu,secu,thiu,还知道了从上面传下来的
d
d
d,这个
d
d
d不只是暴力里面的深度,是根的最优情况
然后
m
a
x
(
t
h
i
u
,
d
)
max(thi_u,d)
max(thiu,d)就是根到点
u
u
u的最优距离
然而最终的答案是
s
e
c
u
sec_u
secu要×个2,这个
s
e
c
u
sec_u
secu是中间大的
所以找出中间大的是×2的那个
Code:
#include <bits/stdc++.h>
#define maxn 200010
#define LL long long
using namespace std;
struct Edge{
int to, next;
LL len;
}edge[maxn << 1];
int num, head[maxn], n, m;
LL fir[maxn], sec[maxn], thi[maxn], ans, deg[maxn], rt, idfir[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void addedge(int x, int y, int z){ edge[++num] = (Edge){y, head[x], z}, head[x] = num; }
void dfs(int u, int pre){
fir[u] = sec[u] = thi[u] = 0;
idfir[u] = 0;
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
LL l = edge[i].len;
if (v != pre){
dfs(v, u);
if (fir[v] + l > fir[u]){
thi[u] = sec[u], sec[u] = fir[u], fir[u] = fir[v] + l, idfir[u] = v;
// if (sec[v] + l > sec[u]) sec[u] = sec[v] + l;
} else if (fir[v] + l > sec[u]) thi[u] = sec[u], sec[u] = fir[v] + l;
else if (fir[v] + l > thi[u]) thi[u] = fir[v] + l;
}
}
// ans = max(ans, fir[u] + sec[u] + sec[u] + max(d, thi[u]));
}
void dfs1(int u, int pre, LL d){
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
LL l = edge[i].len;
if (v != pre){
if (v == idfir[u]) dfs1(v, u, max(sec[u], d) + l);
else dfs1(v, u, max(fir[u], d) + l);
}
}
LL x = fir[u], y = sec[u], z = max(d, thi[u]);
if (z > x) swap(z, x);
if (y > x) swap(y, x);
if (z > y) swap(z, y);
ans = max(ans, x + y + y + z);
// ans = max(ans, fir[u] + sec[u] + sec[u] + max(d, thi[u]));
// printf("%d %d %d %d %d\n", u, fir[u], sec[u], thi[u], d);
}
int main(){
freopen("pc.in", "r", stdin);
freopen("pc.out", "w", stdout);
n = read(), m = read();
for (int i = 1; i <= m; ++i){
int x = read(), y = read(), z = read();
addedge(x, y, z), addedge(y, x, z);
++deg[x], ++deg[y];
}
for (int i = 1; i <= n; ++i) if (deg[i] > 1) rt = i;
dfs(rt, 0);
/* for (int i = 1; i <= n; ++i){// printf("rt : %d\n", i);
dfs(i, 0, 0);
}*/
dfs1(rt, 0, 0);
printf("%lld\n", ans);
return 0;
}