zoukankan      html  css  js  c++  java
  • 【树】HNOI2014 米特运输

    题目大意

    洛谷链接
    给出一课点带权的树,修改一些点的权值使该树满足:

    • 同一个父亲的儿子权值必须相同
    • 父亲的取值必须是所有儿子权值之和

    输入格式

    第一行是一个正整数(N),表示节点的数目。
    接下来(N)行,每行一个正整数,其中的第(i)行表示第(i)个节点的权值。
    再接下来是(N-1)行,每行两个正整数(a,b)表示(a,b)之间有路径((a≠b))。

    数据范围

    (N<500000,A[j]<10^8)

    输出格式

    输出一个整数表示最少需要修改的点的数目。

    样例输入

    5
    5
    4
    3
    2
    1
    1 2
    1 3
    2 4
    2 5

    样例输出

    3

    样例解释

    一个最优解是将(A[1])改成8,(A[3])改成4,(A[5])改成2。

    思路

    只要确定了一个点的值就可以知道整棵树的值了。
    将路径上权值的累乘即为(f[i])(f[i])相同的表示他们同属于同一种合法方案,最后排序寻找相同最多的即可。
    所有权值累乘会超(long long),这里学到的就是运用(log)转为加法,可以不开高精度。
    (log)就肯定要开浮点数,本题似乎没有精度问题,不过设个极小值判断一下也是可以的。
    (log(a×b)=log(a)+log(b))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=500000+10;
    vector<int> edge[maxn];//用vector存下边,比较好写
    ll n,cnt=1,ans=1;
    double a[maxn],f[maxn];
    
    void add(int x,int y) {
        edge[x].push_back(y);
    }
    
    void dfs(int rt,double sum) {
        f[rt]=sum+log((double)a[rt]);
        for(int i=0; i<edge[rt].size(); i++) {
            int Next=edge[rt][i];
            dfs(Next,sum+log((double)edge[rt].size()));
        }
    }
    
    int main() {
        scanf("%lld",&n);
        for(int i=1; i<=n; i++)
            scanf("%lf",&a[i]);
    
        for(int i=1; i<n; i++) {
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        dfs(1,log(1.0));
    
        sort(f+1,f+n+1);
    
        for(int i=2; i<=n; i++)
            if(f[i]-f[i-1]<=1e-8) {
                cnt++;
                ans=max(ans,cnt);
            } else cnt=1;
        printf("%lld
    ",n-ans);
        return 0;
    }
    
  • 相关阅读:
    美化的滚动条
    网站系统开发参考网址
    正则表达式获取URL参数
    类实例 及 实例化对象 对象引用
    C# 静态方法 静态属性 调用静态方法
    C# 静态方法调用非静态方法
    winform 窗体间传值
    从数据库中读出数据并输出
    数据库链接字符串
    DbHelper
  • 原文地址:https://www.cnblogs.com/Midoria7/p/12781088.html
Copyright © 2011-2022 走看看