性质一:树的直径必须经过一个点,且这个点为这个直径的中点(中点可以为一条路径的中点)
性质二:修改一条已知直径的权值,若其它直径与该直径有相交部分,则其它直径权值也会更改(好像比性质一更显然些)
所以我们就用性质二来做。
前后求两次直径,差即为答案。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N= 2e5 + 5 ;
int n, u, v, w, p, ans, d1, d2, last;
int d[ N] , dd[ N] ;
int cnt= 1 , head[ N] ;
struct edge{ int next, from, to, w, f; } e[ N<< 1 ] ;
inline void add ( int u, int v, int w)
{
cnt++ ;
e[ cnt] . next= head[ u] ;
e[ cnt] . from= u;
e[ cnt] . to= v;
e[ cnt] . w= w;
head[ u] = cnt;
}
void dfs ( int u, int fa, int now)
{
if ( now> ans) ans= now, p= u;
for ( register int i= head[ u] ; i; i= e[ i] . next) if ( e[ i] . to!= fa) dfs ( e[ i] . to, u, now+ e[ i] . w) ;
}
void dfs2 ( int u, int fa)
{
for ( register int i= head[ u] ; i; i= e[ i] . next)
if ( e[ i] . to!= fa)
{
d[ e[ i] . to] = d[ u] + e[ i] . w;
dfs2 ( e[ i] . to, u) ;
}
}
void dfs3 ( int u, int fa)
{
for ( register int i= head[ u] ; i; i= e[ i] . next)
if ( e[ i] . to!= fa)
{
dd[ e[ i] . to] = dd[ u] + e[ i] . w;
dfs3 ( e[ i] . to, u) ;
}
}
void dfs4 ( int u, int fa)
{
for ( register int i= head[ u] ; i; i= e[ i] . next)
if ( e[ i] . to!= fa && dd[ u] + e[ i] . w+ d[ e[ i] . to] == ans)
{
e[ i] . f= e[ i^ 1 ] . f= 1 ;
dfs4 ( e[ i] . to, u) ;
}
}
signed main ( ) {
scanf ( "%lld" , & n) ;
for ( register int i= 1 ; i< n; ++ i) scanf ( "%lld%lld%lld" , & u, & v, & w) , add ( u, v, w) , add ( v, u, w) ;
dfs ( 1 , 0 , 0 ) ; d1= p; dfs2 ( p, 0 ) ;
ans= 0 ; dfs ( p, 0 , 0 ) ; d2= p; dfs3 ( p, 0 ) ;
dfs4 ( p, 0 ) ;
last= ans;
for ( register int i= 1 ; i<= cnt; ++ i) e[ i] . w- = e[ i] . f;
ans= 0 ; dfs ( 1 , 0 , 0 ) ; d1= p;
ans= 0 ; dfs ( p, 0 , 0 ) ;
printf ( "%lld\n" , last) ;
printf ( "%lld\n" , last- ans) ;
return 0 ;
}