51Nod 1737 配对(树的重心)

时间:2021-12-29 09:49:56

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1737

题意:

51Nod 1737 配对(树的重心)

思路:

树的重心。

树的重心就是其所以子树的最大的子树结点数最少,删除这个点后最大连通块的结点数最小,也就说各个连通块尽量平衡。

这道题的话就是先求一个重心,然后求各个点到重心的距离之和。

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
using namespace std; const int maxn=1e5+;
const int INF=0x3f3f3f3f; int n; vector<pair<int,int> > edge[maxn]; int zx,sz;
int son[maxn],vis[maxn];
long long ww[maxn]; //各个点到重心的距离 void init()
{
for(int i=;i<=n;i++)
edge[i].clear();
memset(vis,,sizeof(vis));
memset(ww,,sizeof(ww));
sz=INF;
zx=-;
} void dfs(int u)
{
vis[u]=;
son[u]=;
int temp=;
for(int i=;i<edge[u].size();i++)
{
int v=edge[u][i].first;
if(!vis[v])
{
dfs(v);
son[u]+=son[v]+; //找到该子树中的最大结点数
temp=max(temp,son[v]+);
}
}
temp=max(temp,n-son[u]-); //删去重心后子树最大结点数和非重心的子树比较
if(temp<sz)
{
zx=u;
sz=temp;
}
} void sum(int u)
{
vis[u]=;
for(int i=;i<edge[u].size();i++)
{
int v=edge[u][i].first;
if(!vis[v])
{
ww[v] =ww[u]+edge[u][i].second;
sum(v);
}
}
} int main()
{
//freopen("D:\\input.txt","r",stdin);
while(~scanf("%d",&n))
{
init();
int u,v,w;
for(int i=;i<=n-;i++)
{
scanf("%d%d%d",&u,&v,&w);
edge[u].push_back(make_pair(v,w));
edge[v].push_back(make_pair(u,w));
} dfs();
memset(vis,,sizeof(vis));
sum(zx);
long long ans=;
for(int i=;i<=n;i++)
ans+=ww[i];
printf("%lld\n",ans);
}
}