• HDU-2196 Computer (树形DP)


    最近在看树形DP,这题应该是树形DP的经典题了,写完以后还是有点感觉的。之后看了discuss可以用树分治来做,以后再试一试。



    题目大意

    找到带权树上离每个点的最远点。︿( ̄︶ ̄)︿


    题解:

    对于每一个点的最远点,就是以这个点为根到所有叶子节点的最长距离。但是如果确定根的话,除了根节点外,只能找到每个节点(度数-1)个子树的最大值,剩下一个子树是该节点当前的父亲节点。

    所以当前节点的最远点在当前节点子树的所有叶子节点以及父亲节点的最远点上(当父亲节点的最远点不在当前节点的子树上时),

    如果父亲节点的最远点在当前子树上时候,取父亲节点的第二大最远点子树上。(具体的看代码)

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #define MAX_NUM                10020
    #define mem(a,b)    memset(a,b,sizeof(a))
    using namespace std;
    typedef long long int LL;
    struct  no
    {
        LL v,next,w;    
    }edge[4*MAX_NUM];
    int stu[MAX_NUM];
    int col = 0;
    void add(LL u , LL v,LL w){
        edge[col].v = v;
        edge[col].w = w;
        edge[col].next = stu[u];
        stu[u] = col++;
    }
    LL dp[MAX_NUM][2];
    LL sec[MAX_NUM];
    LL sett[MAX_NUM];
    bool flag[MAX_NUM];
    LL fdfs(LL u){
        dp[u][0] = 0;
        for (int i = stu[u]; i != -1 ; i = edge[i].next){
            LL v = edge[i].v;
            if(!flag[v]){
                flag[v] = true;
                LL num = fdfs(v)+edge[i].w;
                if(num>=dp[u][0]){
                    sec[u] = dp[u][0];
                    dp[u][0] = num;
                    sett[u] = v;
                }
                else if(num>=sec[u]){
                    sec[u] = num;
                }
            }
        }
        return dp[u][0];
    }
    void ddfs(LL u){
        for (int i = stu[u]; i != -1 ; i = edge[i].next){
            LL v = edge[i].v;
            if(!flag[v]){
                flag[v] = true;
                if(sett[u]!=v)
                    dp[v][1] = max(dp[u][0], dp[u][1])+edge[i].w;
                else
                    dp[v][1] = max(sec[u],dp[u][1])+edge[i].w;
                ddfs(v);
            }
        }
    } 
    int main(int argc, char const *argv[])
    {
        int n;
        while(~scanf("%d",&n)){
            mem(dp,0);
            mem(flag,false);
            mem(sett,0);
            mem(stu,-1);
            mem(sec,-1);
            LL a,b;
            col = 0;
            for (int i = 2; i <= n ; ++i)
            {
                scanf("%lld%lld",&a,&b);
                add(i,a,b);
                add(a,i,b);
            }
            flag[1]  = true;
            fdfs(1);
            mem(flag,false);
            flag[1] = true;
            ddfs(1);
            for (int i = 1; i <= n ; ++i)
            {
                printf("%lld
    ",max(dp[i][0],dp[i][1]));
            }
        }
        return 0;
    }
  • 相关阅读:
    性能测试策略和关注指标
    ES7.17.1安装
    java 复制对象
    Java 实现树结构计算各个节点数的和
    自定义初始化ES实体类
    .net core datatable 导出 pdf 支持中文
    VSCode 快捷键(整理)
    国标平台LiveGBS GB28181接入录像机NVR、摄像头时没有通道 通道数位0的检查办法
    基于docker搭建Android cordova开发环境
    SpringBoot整合邮箱发送邮件
  • 原文地址:https://www.cnblogs.com/miamiao/p/6926155.html
Copyright © 2020-2023  润新知