• 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;
    }
  • 相关阅读:
    关于如何使用Microsoft Word发博客
    使用Word发表博客园博文
    利用Word发布文章到博客
    图解利用Word来发布博客
    [转载]如何将word文档直接发布到新浪博客
    如何用word发布博客文章到新浪|网易|博客园?
    word 2010发布文章到博客园
    使用Word2010发布博客到博客园
    C++ 虚函数表解析
    GlobalAlloca GlobalLock GlobalUnlock函数的作用
  • 原文地址:https://www.cnblogs.com/miamiao/p/6926155.html
Copyright © 2020-2023  润新知