【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;
}

猜你喜欢

转载自www.cnblogs.com/AWCXV/p/10679237.html