zoukankan      html  css  js  c++  java
  • [CF1087D]Minimum Diameter Tree

    link

    题目大意

    有$n$个点的前边权为$0$的树,你要加入$S$边权总量,可以为分数,使得当前树的直径最小。

    题目分析

    题目过于毒瘤,导致于最后$1$个小时一直在做此题,没想到真的只是一个结论一样的东西。

    我们不要想十分复杂,我们发现数的直径两端都会在度数为$1$的点上,就是叶子节点。然后呢我们就可以把此题转换成让两两叶子节点直接距离相等且最短时是多少。

    就比如当此时我们便让$(1,3),(1,4),(1,6),(3,6),(3,4),(4,6)$距离都是一样的,答案是$0.5$。

    所以现在我们要做的是将树的直径平分,这是一个定值,也就是答案,我们发现怎么去构造呢,易看图发现有些边权值为$0$$(2,5)$,这样会使每两个叶子节点只会走两个权值不为$0$的,也就是两个叶子节点挨着边。

    所以我们可以发现答案为$frac{(n-1) imes k}{C_{ans}^2}$,其中$ans$为叶子节点个数,$k$为一共需要加到$k$这个权值,而$n-1$是因为每条叶子节点挨着的边都遍历过$n-1$遍,整理的答案为$frac{2 imes k}{ans}$

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    const int MAXN=500001;
    int n,k,du[MAXN],ans;
    int main(){
        n=read(),k=read();
        for(int i=1;i<n;i++)du[read()]++,du[read()]++;
        for(int i=1;i<=n;i++)
            if(du[i]==1) ans++;
        printf("%.10lf",2*1.0*k/ans);
    }
    View Code
  • 相关阅读:
    Python爬虫一
    Python爬虫二
    DRF框架中的演变View
    计算时间复杂度例题
    vue2.x webpack打包资源路径问题
    vs code运行c语言 控制台乱码 问题
    解决视频的声音和画面不同步问题
    c语言数据结构,静态链表,结构体数组
    swagger @ApiModel添加实体类不生效
    计算及校验海明码的3个举例
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/10167988.html
Copyright © 2011-2022 走看看