• HDU2196computer(树上最远距离 + DP)


    Computer

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


    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
     

     题意:以1为根,建立一棵树,每个节点之间的长度为len,然后求每个节点到叶子的最远距离;

    分析:求i节点,两种可能,一种是从i的子树得到最远距离,第二种是从父节点得到最远距离,所以两次dfs,第一次统计所有节点从子树到叶子的最远距离和次远距离,第一次看这道题,不明白次远距离有什么用,看到第二次dfs就明白了,第二次就要判断i是从子树还是父节点过来的,此时已经求出了子树方向的所有最长距离,最要知道父节点方向最长距离就ok了,比较一下嘛,然后父节点的最远距离有两种可能,一种是经过 i 而来的,所以求 i 父节点方向的最远距离就是 i 父节点的次最远距离了,第二种是不经过 i 而来的,所以 i 父节点方向的最远距离就是他

    ----------------------------------------------------------------------------

    2016/3/17更新

    今天又看了一遍好费劲,其实第一次dfs1主要是求了根节点1到左右两边节点的最远距离,一个最远,一个次远,然后第二次还是从根节点dfs2,主要就是判断每一个点是从子树来的还是从父节点来的,所以先判断根节点的儿子,因为根节点已经在第一部求出来了到两边的距离。

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstring>
     4 #include <cstdio>
     5 using namespace std;
     6 const int Max = 10000 + 10;
     7 struct Node
     8 {
     9     int to,next,len;
    10 };
    11 Node edge[2 * Max];
    12 int head[Max], tol;
    13 int maxn[Max],maxnId[Max]; //最远距离和最远距离对应的序号
    14 int smaxn[Max],smaxnId[Max]; //次远距离和次远距离对应的序号
    15 void add_edge(int a, int b, int len)
    16 {
    17     edge[tol].to = b;
    18     edge[tol].next = head[a];
    19     edge[tol].len = len;
    20     head[a] = tol++;
    21 }
    22 void dfs1(int u, int p)
    23 {
    24     maxn[u] = smaxn[u] = 0;
    25     for(int i = head[u]; i != -1; i = edge[i].next)
    26     {
    27         int v = edge[i].to;
    28         if(v == p)  //如果是父节点跳过
    29             continue;
    30         dfs1(v, u);
    31         if(smaxn[u] < maxn[v] + edge[i].len)  //如果子节点的最远距离大于次远距离,就更新次远距离;先更新次远距离,由次远距离和最远距离比较更新最远距离
    32         {
    33             smaxn[u] = maxn[v] + edge[i].len;
    34             smaxnId[u] = v;
    35             if(smaxn[u] > maxn[u])
    36             {
    37                 swap(smaxn[u], maxn[u]);
    38                 swap(smaxnId[u], maxnId[u]);
    39             }
    40         }
    41     }
    42 }
    43 void dfs2(int u, int p)
    44 {
    45     for(int i = head[u]; i != -1; i = edge[i].next)
    46     {
    47         int v = edge[i].to;
    48         if(v == p)
    49             continue;
    50         if(v == maxnId[u])  //如果父节点方向最远距离经过这个子节点
    51         {
    52             if(smaxn[u] + edge[i].len > smaxn[v]) //选择次远距离,因为最远距离经过v点
    53             {
    54                 smaxn[v] = smaxn[u] + edge[i].len;
    55                 smaxnId[v] = u;
    56                 if(maxn[v] < smaxn[v])
    57                 {
    58                     swap(maxn[v], smaxn[v]);
    59                     swap(maxnId[v], smaxnId[v]);
    60                 }
    61             }
    62         }
    63         else
    64         {
    65             if(maxn[u] + edge[i].len > smaxn[v])
    66             {
    67                 smaxn[v] = maxn[u] + edge[i].len;
    68                 smaxnId[v] = u;
    69                 if(maxn[v] < smaxn[v])
    70                 {
    71                     swap(maxn[v], smaxn[v]);
    72                     swap(maxnId[v], smaxnId[v]);
    73                 }
    74             }
    75         }
    76         dfs2(v, u);
    77     }
    78 }
    79 int main()
    80 {
    81     int n,v,len;
    82     while(scanf("%d", &n) != EOF)
    83     {
    84         tol = 0;
    85         memset(head, -1, sizeof(head));
    86         for(int i = 2; i <= n; i++)
    87         {
    88             scanf("%d%d", &v, &len);
    89             add_edge(i, v, len);
    90             add_edge(v, i, len);
    91         }
    92         dfs1(1, -1); //向下
    93         dfs2(1, -1);
    94         for(int i = 1; i <= n; i++)
    95             printf("%d
    ", maxn[i]);
    96     }
    97     return 0;
    98 }
    View Code
  • 相关阅读:
    清除浮动的集中方式
    css动画
    [Asp.net]c#中的斜杠和反斜杠
    C# ASPX页面做上传提示:超过了最大请求长度,解决方法
    在asp.net中用客户端上传控件上传文件( 需要注意的)
    jquery clone 与 clone(true) 的区别
    【转载】用div+css模拟表格对角线
    .net2.0中的Json序列化数据
    jquery操作checkbox的选中与不选中,解决只有一次有用。
    转:不同服务器数据库之间的数据操作[含远程数据库备份]
  • 原文地址:https://www.cnblogs.com/zhaopAC/p/5190285.html
Copyright © 2020-2023  润新知