zoukankan      html  css  js  c++  java
  • HDU 2136:Computer(树形DP)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=2196

    Computer
     
     

    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

    题意:给出一棵树,求树中每个节点到树中任意其他节点的最大距离。
    思路:想了挺久还是不会做,只能学习一下别人的了。http://blog.csdn.net/shuangde800/article/details/9732825
       和之前那道水题完全天壤之别。
       用两次dfs来求出最大的距离。第一次dfs是求出节点i的子树节点到i的最大距离,用dp[i][0]表示(从上往下)。第二次dfs是求出不在节点i的子树的节点中的其他节点到节点i的最大距离(从下往上),即到父节点的最大距离 + 父节点和该节点的w(父节点的最大距离的路径不能包含i,若包含要用次大距离),用dp[i][1]表示。答案就取max(dp[i][0], dp[i][1]).
      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <string>
      6 #include <cmath>
      7 #include <queue>
      8 #include <vector>
      9 using namespace std;
     10 #define N 10010
     11 struct node
     12 {
     13     int v, nxt, w;
     14 }edge[N*2];
     15 int head[N], tot;
     16 int dp[N][2];
     17 bool vis[N];
     18 
     19 /*
     20 dp[i][0],表示顶点为i的子树的,距顶点i的最长距离
     21 dp[i][1],表示Tree(i的父节点)-Tree(i)的最长距离+i跟i的父节点距离
     22 Tree(x)表示以x为根的子树
     23 */
     24 void add(int u, int v, int w)
     25 {
     26     edge[tot].v = v;
     27     edge[tot].w = w;
     28     edge[tot].nxt = head[u];
     29     head[u] = tot++;
     30     edge[tot].v = u;
     31     edge[tot].w = w;
     32     edge[tot].nxt = head[v];
     33     head[v] = tot++;
     34 }
     35 
     36 void dfs1(int u) //回溯的时候找到各个节点子树距节点的最大距离
     37 {
     38     vis[u] = 1;
     39     for(int i = head[u]; ~i; i = edge[i].nxt) {
     40         int v = edge[i].v, w = edge[i].w;
     41         if(vis[v]) continue;
     42         dfs1(v);
     43         dp[u][0] = max(dp[u][0], w + dp[v][0]);
     44     }
     45 }
     46 
     47 void dfs2(int u) //从上往下找不属于该节点子树的节点到该节点的最大距离,即从另一个方向找
     48 {
     49     vis[u] = 1;
     50     int ma1 = 0, ma2 = 0, tmp, v1, v2;
     51     for(int i = head[u]; ~i; i = edge[i].nxt) {    //从子节点到该节点父节点最大距离
     52         int v = edge[i].v, w = edge[i].w;
     53         if(vis[v]) continue;
     54         tmp = dp[v][0] + w;
     55         if(tmp > ma1) {
     56             ma2 = ma1, v2 = v1, ma1 = tmp, v1 = v;
     57         } else if(tmp > ma2) {
     58             ma2 = tmp, v2 = v;
     59         }
     60     }
     61 
     62     if(u != 1) {  //有父节点有兄弟的话,找从其他节点到父节点的最长距离
     63         tmp = dp[u][1];
     64         int v = 0;    //这个时候一定是用dp[u][1],所以不受限制
     65         if(tmp > ma1) {
     66             ma2 = ma1, v2 = v1, ma1 = tmp, v1 = v;
     67         } else if(tmp > ma2) {
     68             ma2 = tmp, v2 = v;
     69         }
     70     }
     71 
     72     for(int i = head[u]; ~i; i = edge[i].nxt) {
     73         int v = edge[i].v, w = edge[i].w;
     74         if(vis[v]) continue;
     75         if(v == v1) {    //如果最长的距离的路径经过该节点,那么只能选次大的
     76             dp[v][1] = ma2 + w;
     77         } else {    //否则可以选最大的
     78             dp[v][1] = ma1 + w;
     79         }
     80         dfs2(v);
     81     }
     82 }
     83 
     84 int main()
     85 {
     86     int n;
     87        while(~scanf("%d", &n)) {
     88            memset(head, -1, sizeof(head));
     89            tot = 0;
     90            for(int i = 2; i <= n; i++) {
     91                int v, w;
     92                scanf("%d%d", &v, &w);
     93                add(i, v, w);
     94            }
     95 
     96            memset(vis, 0, sizeof(vis));
     97            memset(dp, 0, sizeof(dp));
     98            dfs1(1);
     99            memset(vis, 0, sizeof(vis));
    100            dfs2(1);
    101 
    102            for(int i = 1; i <= n; i++) {
    103                printf("%d
    ", max(dp[i][0], dp[i][1]));
    104            }
    105        }
    106 
    107     return 0;
    108 }
     
  • 相关阅读:
    PHP7放弃大礼包(微信支付回调签名错误)
    PHP CURL中传递cookie的方法
    php-5.3源码编译autoconf版本不符合解法
    单例模式使用小介绍
    centos源码编译安装nginx过程记录
    PHP语言开发Paypal支付demo的具体实现
    Redis安全与持久化(适合小白阅读)
    mac当你有多个版本的命令存在是怎么使用最新版本
    设置让php能够以root权限来执行exec() 或者 shell_exec()
    git冲突解决
  • 原文地址:https://www.cnblogs.com/fightfordream/p/5801284.html
Copyright © 2011-2022 走看看