在纸上画一棵树,发现如果是回路,每条边走两次就够了
那么不是回路,有些边就不需要走两次了
发现,任意选择两点,从端点出发,路上一旦出现分支就出去走两遍回来
这样走到两一个端点的时候,两点间的距离其实只被走了一次
这样的话就求树的直径就好了
有点像规律题呢
#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;
} 
京公网安备 11010502036488号