链接:https://ac.nowcoder.com/acm/contest/553/E
来源:牛客网
Chino的数学很差,因此Cocoa非常担心。今天,Cocoa要教Chino和三角形有关的知识。
众所周知,,它们能构成三角形的条件是.
另一个众所周知的事实是,“树”是一种包含了个点和条边的连通无向无环图。因此,树上两点之间的简单路径是唯一确定的,也就是说,两点之间的距离是唯一确定的。
现在,Cocoa想要知道,完全随机地从树上取三个点,得到三个距离,这三个距离构成三角形的概率是多少?
题目对Chino来说太难啦,你能帮一帮Chino吗?
树形dp问题 通过简单的枚举我们发现当且只有三个点都是在一条直线上的时候是无法构成三角形的 如果不在一条直线上的话 那么肯定是可以构成等腰三角形 那么就可以愉快的进行树形dp了
dfs 求一下当前节点的子节点数目 那么不满足条件的就是选当前节点 选他的子节点 加上 选他的父亲上面的所以节点
设不满足的数目为cnt 那么就有
cnt += g[son] * g[fa]
cnt += (n - g[fa] )* (g[fa] - 1); // 不包含自己
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
double f[maxn],ans = 0;
int n,u,v;
vector<int> g[maxn];
void dfs(int son,int fa)
{
for(int i = 0; i < g[son].size() ; i++)
{
if(g[son][i]==fa) continue;
dfs(g[son][i],son);
ans+=f[g[son][i]]*f[son];
f[son] += f[g[son][i]];
}
f[son] += 1; // 我为自己代言
ans+=(n-f[son])*(f[son]-1);
}
int main()
{
cin>>n;
double cc = n*(n-1)*(n-2) / 6;
for(int i = 0; i < n - 1; i++)
{
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1,-1);
printf("%.12f\n",(cc-ans)/cc);
return 0;
}