直接去想怎么是合法的三角形,比较麻烦。如果我们想不合法的三角形,我们可以发现因为距离都是树上的距离,只有三个点在一条链上的时候才是不合法的。否则都是合法的三角形。所以要算出不合法的三角形。
也就是我们要枚举每一条链?怎么枚举呢?
这个就和点分治比较类似了,只不过我们不用点分治这么麻烦,我们直接枚举每个点为三角形中间的点v,其余两个点在不同子树中的答案即可。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int n,dp[N],sz[N],res,tot;
vector<int> g[N];
void dfs(int x,int fa){
sz[x]=1; int sum=0;
for(int i=0;i<g[x].size();i++){
int to=g[x][i]; if(to==fa) continue;
dfs(to,x); res+=sum*sz[to];
sum+=sz[to]; sz[x]+=sz[to];
}
res+=(n-sz[x])*(sz[x]-1);
}
signed main(){
cin>>n;
for(int i=1,a,b;i<n;i++)
scanf("%lld %lld",&a,&b),g[a].push_back(b),g[b].push_back(a);
dfs(1,1); tot=n*(n-1)*(n-2)/6;
printf("%.8lf\n",(double)(tot-res)/tot);
return 0;
}