【Codeforces 1086B】Minimum Diameter Tree
【链接】 我是链接,点我呀:)
【题意】
【题解】
统计叶子节点个数m 把每条和叶子节点相邻的边权设置成s/cnt就可以了 这样答案就是2*s/m(直径最后肯定是从一个叶子节点开始,到另外一个叶子节点结束)证明:
设dis(i,j)表示节点i和节点j之间的权值和
设a[1],a[2]..a[m]是m个叶子节点
则
\(max(dis(a[i],a[j])) >= ∑\frac{dis(a[i],a[j]) }{ \frac{m*(m-1)}{2|} }\)
即\(\frac{m*(m-1)}{2}*max(dis(a[i],a[j]))>=∑dis(a[i],a[j])\)
而会发现每一条边对不等式右边的贡献至少是为\(1*(m-1)\)的也就是m-1
最坏的情况就是,每条边左边只有一个叶子节点,然后右边有m-1个叶子节点。贡献就是最小的m-1
所以\(\frac{m*(m-1)}{2}*max(dis(a[i],a[j]))>=∑dis(a[i],a[j])>=(m-1)*∑e[i]=(m-1)*s\)
然后就能得到max(dis(a[i],a[j]))>=2*s/m
【代码】
#include <bits/stdc++.h>
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i>= b;i--)
#define ll long long
using namespace std;
const int N = 1e5;
int n,s;
int du[N+10];
int main(){
ios::sync_with_stdio(0),cin.tie(0);
cin >> n >> s;
rep1(i,1,n-1){
int x,y;
cin >> x >> y;
du[x]++;du[y]++;
}
int m = 0;
double ans = 2*s;
rep1(i,1,n){
if (du[i]==1){
m++;
}
}
ans = ans/m;
cout<<fixed<<setprecision(15)<<ans<<endl;
return 0;
}