对于一棵N个结点的树,其N-1条边有各自的边权(长度),求树上所有结点两两之间的距离和,
即:
∑i=1n−1∑j=i+1ndistance(i,j)\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}distance(i,j)i=1∑n−1j=i+1∑ndistance(i,j)
分析:
要求求 一棵N个结点的树 上 所有的任意两点之间的距离和;
那么 任意一条边对距离和的贡献 = 左端结点个数 * 右端结点个数 * 边权
和求重心类似,一次DFS即可,任选一个为根结点开始DFS;
对任意一条 边u -> v,右端结点个数 就是 向下遍历以v为根的子树的结点个数,那么 左端结点个数 就是 N - 右端点个数,相乘后再乘上边权即可。
int dfs(int u) //每次返回以u为根的子树的结点数量
{
vis[u]=true;
int sum=0;
for(int i=head[u];i!=-1;i=e[i].next)
{
if(vis[e[i].v])
continue;
int t=dfs(e[i].v); //u->v的右端结点个数,即以v为根的子树的结点个数
ans+=(N-t)*t*e[i].w; //ans+=左端*右端*边权
sum+=t; //统计
}
return sum+1; //+1为结点u本身
}
//ans即为最终答案

本文介绍了如何使用DFS解决一棵N个结点的树中所有结点两两之间的距离和问题。通过分析,每条边对总距离的贡献等于左端结点个数乘以右端结点个数再乘以边权。通过一次以任意结点为根的DFS遍历,可以计算出这个和。
3万+

被折叠的 条评论
为什么被折叠?



