在纸上画一棵树,发现如果是回路,每条边走两次就够了

那么不是回路,有些边就不需要走两次了

发现,任意选择两点,从端点出发,路上一旦出现分支就出去走两遍回来

这样走到两一个端点的时候,两点间的距离其实只被走了一次

这样的话就求树的直径就好了

有点像规律题呢

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 5e5+10;
int n,ans,temp;
struct edge{
    int to,nxt,w;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int w){
    d[++cnt] = (edge){v,head[u],w},head[u]=cnt;
}
//f表示最大,ci表示次大
int f[maxn],ci[maxn]; 
void dfs(int u,int fa)
{
    for(int i=head[u];i;i=d[i].nxt )
    {
        int v = d[i].to;
        if( v==fa )    continue;
        dfs(v,u);
        if( f[v]+d[i].w>=f[u] )
            ci[u] = f[u],f[u] = f[v]+d[i].w;     
        else if( ci[u]<f[v]+d[i].w )
            ci[u] = f[v]+d[i].w;
    }
}
void DP(int u,int fa)
{
    for(int i=head[u];i;i=d[i].nxt )
    {
        int v = d[i].to;
        if( v== fa)    continue;
        if( f[u]==f[v]+d[i].w )
            temp = max( temp,ci[u]+f[v]+d[i].w );
        else 
            temp = max( temp,f[u]+f[v]+d[i].w );
        DP(v,u);
    }
}
signed main()
{
    cin >> n;
    for(int i=1;i<n;i++)
    {
        int l,r,w; cin >> l >> r >> w;
        add(l,r,w); add(r,l,w);
        ans += w*2;
    }
    dfs(1,0);
    DP(1,0);
    cout << ans-temp;
}