HDU - 2376
Average distance
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1980 Accepted Submission(s): 717
Special Judge
Problem Description
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 (d01 + d02 + d03 + d04 + d12 +d13 +d14 +d23 +d24 +d34)/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
题目就是求所有路径之和,再除以总的边的数量即可。
这道题比较巧妙,就是我们分析每一条边的贡献值,每一条边的贡献就是左右两个端点的size之积再乘以这条边的长度即可。
所以我们用dfs一遍,求出每个点的子树大小即可。
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e4+10;
int T,n,sz[N],res;
int head[N],nex[N<<1],to[N<<1],w[N<<1],tot;
inline void add(int a,int b,int c){
to[++tot]=b; w[tot]=c; nex[tot]=head[a]; head[a]=tot;
}
void dfs(int x,int fa){
sz[x]=1;
for(int i=head[x];i;i=nex[i]){
if(to[i]==fa) continue;
dfs(to[i],x); sz[x]+=sz[to[i]];
res+=(n-sz[to[i]])*sz[to[i]]*w[i];
}
}
signed main(){
scanf("%lld",&T);
while(T--){
memset(head,0,sizeof head); res=tot=0;
scanf("%lld",&n);
for(int i=1;i<n;i++){
int a,b,c; scanf("%lld %lld %lld",&a,&b,&c);
a++; b++; add(a,b,c); add(b,a,c);
}
dfs(1,0);
printf("%.7lf\n",res*2.0/n/(n-1));
}
return 0;
}