zoukankan      html  css  js  c++  java
  • hdu 2196 树形DP

    Computer

    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2390    Accepted Submission(s): 1219


    Problem Description
    A school bought the first computer some time ago(so this computer's id is 1). During the recent years the school bought N-1 new computers. Each new computer was connected to one of settled earlier. Managers of school are anxious about slow functioning of the net and want to know the maximum distance Si for which i-th computer needs to send signal (i.e. length of cable to the most distant computer). You need to provide this information.


    Hint: the example input is corresponding to this graph. And from the graph, you can see that the computer 4 is farthest one from 1, so S1 = 3. Computer 4 and 5 are the farthest ones from 2, so S2 = 2. Computer 5 is the farthest one from 3, so S3 = 3. we also get S4 = 4, S5 = 4.
     
    Input
    Input file contains multiple test cases.In each case there is natural number N (N<=10000) in the first line, followed by (N-1) lines with descriptions of computers. i-th line contains two natural numbers - number of computer, to which i-th computer is connected and length of cable used for connection. Total length of cable does not exceed 10^9. Numbers in lines of input are separated by a space.
     
    Output
    For each case output N lines. i-th line must contain number Si for i-th computer (1<=i<=N).
     
    Sample Input
    5 1 1 2 1 3 1 1 1
     
    Sample Output
    3 2 3 4 4
     
    Author
    scnu
     
    Recommend
    lcy
     
    目测了众神中文算法后,自己code出来了。
    两次dfs:
    1.第一次,求出以当前节点u为树根的子树中离u的最大、次大权值及该路径中u的前一个节点; (后序遍历)
    2.第二次,因为在第一次中求出了当前点u在其子树中的两个不同路径最大权,那么以它出发的路径最大权为:

     max{子树路径最大权,父节点fa路径最大权(如果该路径前一节点 != u)/次大权(如果该路径前一节点 != u) + 当前边权}。(前序遍历)

     有向树即可,AC代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<map>
    
    using namespace std;
    
    #define LL long long
    #define ULL unsigned long long
    #define UINT unsigned int
    #define MAX_INT 0x7fffffff
    #define cint const int
    #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
    #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
    
    #define MAXN 11111
    #define MAXM 22222>>1
    
    struct edge{
        int u, v, w, nxt;
    }e[MAXM];
    int h[MAXN], cc, n;
    int fir_max[MAXN], sec_max[MAXN];
    int fir_id[MAXN], sec_id[MAXN];
    
    void add(int u, int v, int w){
        e[cc]=(edge){u, v, w, h[u]};
        h[u]=cc++;
    }
    
    void two_dis(int u){
        fir_max[u] = sec_max[u] = 0;
        for(int i=h[u]; i!=-1; i=e[i].nxt){
            int v=e[i].v, w=e[i].w;
            two_dis(v);                                 //搞完所有子节点再搞当前点
            if(fir_max[v]+w>=fir_max[u]){               //>=  考虑到边权为0的情况
                sec_max[u]=fir_max[u];      sec_id[u]=fir_id[u];
                fir_max[u]=fir_max[v]+w;    fir_id[u]=v;
            }
            else if(fir_max[v]+w>=sec_max[u]){
                sec_max[u]=fir_max[v]+w;
                sec_id[u]=v;
            }
        }
    }
    
    void max_dis(int u){
        for(int i=h[u]; i!=-1; i=e[i].nxt){
            int v=e[i].v, w=e[i].w;
            if(fir_id[u]!=v){                           //用从父节点出发的最大权更新
                int tw = w + fir_max[u];
                if(tw>=fir_max[v]){
                    sec_max[v] = fir_max[v];    sec_id[v] = fir_id[v];
                    fir_max[v] = tw;    fir_id[v] = u;
                }
                else if(tw>=sec_max[v]){
                    sec_max[v] = tw;    sec_id[v] = u;
                }
            }
    
            if(sec_id[u]!=v){                           //次大权更新
                int tw = w + sec_max[u];
                if(tw>=fir_max[v]){
                    sec_max[v] = fir_max[v];    sec_id[v] = fir_id[v];
                    fir_max[v] = tw;            fir_id[v] = u;
                }
                else if(tw>=sec_max[v]){
                    sec_max[v] = tw;    sec_id[v] = u;
                }
            }
            max_dis(v);                                 //去搞所有子节点
        }
    }
    
    int main(){
    //    freopen("C:\Users\Administrator\Desktop\in.txt","r",stdin);
        while(scanf(" %d", &n)==1){
            int u, v, w;
    
            memset(h, -1, sizeof(h));       cc=0;
            for(v=2; v<=n; v++){
                scanf(" %d %d", &u, &w);
                add(u, v, w);
            }
            two_dis(1);
            max_dis(1);
            for(u=1; u<=n; u++)
                printf("%d
    ", fir_max[u]);
        }
        return 0;
    }
    
  • 相关阅读:
    MFC9.0 Outlook控件的标题显示无法修改
    VS2010 单文档+多视图+Outlook风格
    在VS2010中使用Outlook工具栏
    在MFC中添加用户自定义消息
    读书笔记——Windows环境下32位汇编语言程序设计(13)关于EXCEPTION_DEBUG_INFO结构体
    读书笔记——Windows环境下32位汇编语言程序设计(9)ANSII字符大小写转大写
    读书笔记——Windows环境下32位汇编语言程序设计(6)使用浮点指令进行64位除法
    读书笔记——Windows环境下32位汇编语言程序设计(5)模态对话框
    读书笔记——Windows环境下32位汇编语言程序设计(3)一些基础知识
    设置自己的RadASM颜色
  • 原文地址:https://www.cnblogs.com/ramanujan/p/3358281.html
Copyright © 2011-2022 走看看