题意:给一棵带权树,输出所有点对间的平均距离。
思路:在总距离中,一条边被计算了多少次取决于边的两端顶点数量的乘积,所以我们统计每条边两端分别有多少顶点。方法是,把树转化为有根树,然后统计每个顶点有多少孩子(包括孩子的孩子),那么边的其中一端顶点的数量就是它加上1。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#include <sstream>
#define INF 1000000000
#define ll long long
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define MAXN 1010
using namespace std;
struct edge{
int u,v,w;
edge(int a=0,int b=0,int c=0){
u=a; v=b; w=c;
}
};
edge edges[20010];
vector<int> G[10010];
vector<int> ch[10010];
int p[10010];
void dfs(int u,int fa){
int d=G[u].size();
for(int i=0;i<d;i++){
int v=edges[ G[u][i] ].v;
if(v!=fa){
dfs(v,p[v]=u);
ch[u].push_back(v);
}
}
}
int cnt[10010];
int dfs2(int x){
if(cnt[x])return cnt[x];
int d=ch[x].size();
cnt[x]+=d;
for(int i=0;i<d;i++){
cnt[x]+=dfs2(ch[x][i]);
}
return cnt[x];
}
int main(){
int t;
cin>>t;
while(t--){
memset(G,0,sizeof(G));
memset(ch,0,sizeof(ch));
memset(p,0,sizeof(p));
memset(cnt,0,sizeof(cnt));
ll n;
cin>>n;
for(int i=1;i<n;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
edges[i*2-1]=edge(u,v,w);
G[u].push_back(i*2-1);
edges[i*2]=edge(v,u,w);
G[v].push_back(i*2);
}
dfs(0,-1);
dfs2(0);
ll ans=0;
for(int i=1;i<n;i++){
int son;
if( p[ edges[i*2-1].u ]==edges[i*2-1].v ){
son=edges[i*2-1].u;
}else{
son=edges[i*2-1].v;
}
ans+= (cnt[son]+1)*(n-cnt[son]-1)*edges[i*2-1].w;
}
ll t=n*(n-1)/2;
printf("%.8lf\n",(ans+0.0)/t);
}
return 0;
}