Given a tree, calculate the average distance between two vertices in the tree. For example, the average distance between two vertices in the following tree is (d 01 + d 02 + d 03 + d 04 + d 12 +d 13 +d 14 +d 23 +d 24 +d 34)/10 = (6+3+7+9+9+13+15+10+12+2)/10 = 8.6.
Input
On the first line an integer t (1 <= t <= 100): the number of test cases. Then for each test case:
One line with an integer n (2 <= n <= 10 000): the number of nodes in the tree. The nodes are numbered from 0 to n - 1.
n - 1 lines, each with three integers a (0 <= a < n), b (0 <= b < n) and d (1 <= d <= 1 000). There is an edge between the nodes with numbers a and b of length d. The resulting graph will be a tree.
Output
For each testcase:
One line with the average distance between two vertices. This value should have either an absolute or a relative error of at most 10 -6
Sample Input
1 5 0 1 6 0 2 3 0 3 7 3 4 2
Sample Output
8.6
解题报告:
就是求出树上任意两点间的距离的和,再求平均值。这样只要知道每个边走过几次,用次数乘上这条边的权值,再把所有边加和,除以路径数就可以。首先,关于路径数,我觉得就像一个有 N个点的完备图,这个图中边的数量,就是这N个点形成的树,树中任意两点组成的边的数量。再来就是每一条路走过多少次,这个不太好想,如题目的图中,求0和3这两个点之间的边总共要经过多少次,其实可以理解为从0左边的点(包括0)到3右边(包括3)总共有多少中走法,那么就是0即其左边点的个数乘3即其右边的个数。求某个点一边的点的个数的方法感觉跟求树的重心的方法有点像,感觉这种方法应该记一下,有一些题都会用到。
ac代码:
#include<stdio.h>
#include<iostream>
#include<map>
#include<vector>
#include<string.h>
#define ll long long
#define mod 1000000007
using namespace std;
const int MAXN=2e5+10;
struct edge{
int y;
int w;
edge(){}
edge(int y,int w):y(y),w(w){}
};
int n;
vector<edge> vv[MAXN];
ll ans;
ll dp[MAXN];
void dfs(int x,int f)
{
int ed=vv[x].size();
for(int i=0;i<ed;i++)
{
edge v=vv[x][i];
if(v.y==f)
continue;
dfs(v.y,x);
dp[x]+=dp[v.y];
ans+=dp[v.y]*(n-dp[v.y])*v.w;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int u,v,w;
ans=0;
for(int i=0;i<n;i++)
{
vv[i].clear();
dp[i]=1;
}
for(int i=0;i<n-1;i++)
{
scanf("%d%d%d",&u,&v,&w);
vv[u].push_back(edge(v,w));
vv[v].push_back(edge(u,w));
}
dfs(0,-1);
printf("%lf\n",ans*2.0/n/(n-1));
}
return 0;
};