• 【bzoj2435】[NOI2011]道路修建 树形dp


    题目描述

    在 W 星球上有 n 个国家。为了各自国家的经济发展,他们决定在各个国家之间建设双向道路使得国家之间连通。但是每个国家的国王都很吝啬,他们只愿意修建恰好 n – 1条双向道路。 每条道路的修建都要付出一定的费用, 这个费用等于道路长度乘以道路两端的国家个数之差的绝对值。例如,在下图中,虚线所示道路两端分别有 2 个、4个国家,如果该道路长度为 1,则费用为1×|2 – 4|=2。图中圆圈里的数字表示国家的编号。

    由于国家的数量十分庞大,道路的建造方案有很多种,同时每种方案的修建费用难以用人工计算,国王们决定找人设计一个软件,对于给定的建造方案,计算出所需要的费用。请你帮助国王们设计一个这样的软件。

    输入

    输入的第一行包含一个整数n,表示 W 星球上的国家的数量,国家从 1到n编号。

    接下来 n – 1行描述道路建设情况,其中第 i 行包含三个整数ai、bi和ci,表示第i 条双向道路修建在 ai与bi两个国家之间,长度为ci。

    输出

    输出一个整数,表示修建所有道路所需要的总费用。

    样例输入

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

    样例输出

    20

    提示

    n = 1,000,000 1≤ai, bi≤n 
    0 ≤ci≤ 10^6


    题解

    这题难点在于求节点个数。

    由于这是一棵树,每个非根节点与其父节点的连线即为题目中要修建的道路。

    于是可以初始化一下每个非根节点与其父节点连线的权值,并递推出每个节点的子树大小size,然后每条道路两端国家个数就为size-(n-size)=2*size-n。

    由于栈的限制,普通的dfs树形dp会爆栈,所以采用bfs。

    #include <stdio.h>
    #include <string.h>
    using namespace std;
    int head[1000001] , to[2000003] , next[2000003] , cnt = 1 , fa[1000001] , q[1000001] , qh = 1 , qt = 1 , si[1000001] , val[2000003] , v[1000001];
    long long ans;
    inline int read()
    {
        int num = 0; char ch = getchar();
        while(ch < '0' || ch > '9') ch = getchar();
        while(ch >= '0' && ch <= '9') num = num * 10 + ch - '0',ch = getchar();
        return num;
    }
    void add(int x , int y , long long z){to[cnt] = y; val[cnt] = z; next[cnt] = head[x]; head[x] = cnt ++ ;}
    int abs(int x){return x > 0 ? x : -x;}
    int main()
    {
        int n , i , x , y , z;
        n = read();
        for(i = 1 ; i < n ; i ++ )
        {
            x = read();
            y = read();
            z = read();
            add(x , y , z);
            add(y , x , z);
        }
        q[1] = 1;
        fa[1] = -1;
        while(qh <= qt)
        {
            x = q[qh ++ ];
            for(i = head[x] ; i ; i = next[i])
            {
                y = to[i];
                if(!fa[y])
                {
                    q[ ++ qt] = y;
                    fa[y] = x;
                    si[y] = 1;
                    v[y] = val[i];
                }
            }
        }
        for(i = qt ; i >= 2 ; i -- )
        {
            x = q[i];
            si[fa[x]] += si[x];
            ans += (long long)v[x] * abs(2 * si[x] - n);
        }
        printf("%lld
    " , ans);
        return 0;
    }

     

  • 相关阅读:
    missing requires of libmysqlclient.so.18()(64bit)
    Ambari安装HDP问题:User root is not allowed to impersonate anonymous.User: hcat is not allowed to impersonate ambari-qa
    ambari2.6.50 openssl 版本问题:SSLError: Failed to connect. Please check openssl library versions. Openssl error upon host registration
    HDP 2.6 requires libtirpc-devel
    Kafka 如何读取offset topic内容 (__consumer_offsets)
    Linux集群时间同步方法
    centos7 ambari2.6.1.5+hdp2.6.4.0 大数据集群安装部署
    Centos7.3离线(rpm方式)安装mysql服务
    ubuntu安装rpm的方法
    kerberos环境storm配置:Running Apache Storm Securely
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/6171076.html
Copyright © 2020-2023  润新知