思路:
树的重心也叫树的质心。
找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,
生成的多棵树尽可能平衡。
考虑每一条边被统计进答案几次,若断开这条边后树形成大小为s1、s2的两个联通块则这条边最多被统计min(s1,s2)次。
树的重心也叫树的质心。
找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,
生成的多棵树尽可能平衡。
考虑每一条边被统计进答案几次,若断开这条边后树形成大小为s1、s2的两个联通块则这条边最多被统计min(s1,s2)次。
删去重心后任意同一联通块中的两点不构成路径。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;
struct asd{
LL w;
int to;
int next;
}e[N*2];
int head[N],tol,n;
void init()
{
memset(head,-1,sizeof(head));
tol=0;
}
void add(int u,int v,LL w)
{
e[tol].w=w;
e[tol].to=v;
e[tol].next=head[u];
head[u]=tol++;
}
bool vis[N];
int d[N];
int minnode,minbalence;
void DFS(int u,int pre)
{
d[u]=1;
int maxson=0;
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if(vis[v]) continue;
vis[v]=true;
DFS(v,u);
d[u]+=d[v];
maxson=max(maxson,d[v]);
}
maxson=max(maxson,n-d[u]);
if(maxson<minbalence)
{
minbalence=maxson;
minnode=u;
}
}
LL ans;
void DFS_2(int u,LL sum)
{
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if(vis[v]) continue;
vis[v]=true;
ans=ans+sum+e[i].w;
DFS_2(v,sum+e[i].w);
}
}
int main()
{
int u,v;
LL w;
scanf("%d",&n);
init();
for(int i=1;i<n;i++){
scanf("%d%d%lld",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
minnode=0;
minbalence=INT_MAX;
memset(d,0,sizeof(d));
memset(vis,false,sizeof(vis));
d[1]=0;
vis[1]=true;
DFS(1,0);
memset(vis,false,sizeof(vis));
ans=0;
vis[minnode]=true;
DFS_2(minnode,0LL);
printf("%lld\n",ans);
return 0;
}