HDU 2196 computer

传送门

Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

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
 

Solution:
 这道题要求的是从树上一点出发的最长路。考虑有根树,不难想到,从树上一点 $u$ 出发的最长路必然是下述两种情况之一:
(1)第一步向下走,(一直向下,走到某叶子节点)
(2)第一步向上走。
考虑树形DP:
$dp[0][u]$ : 从节点 $u$ 向下走的最长路径
$dp[1][u]$ : 从节点 $u$ 向下走的次长路径
这里,次长路径的含义是:与某条选定的最长路径不重合的路径中最长的路径。
$dp[2][u]$ : 从节点 $u$ 第一步向上走所能获得的最长路径
注意:
在 $dp[0][u]$, $dp[1][u]$ 的含义说明中没有强调从节点 $u$ 第一步向下走,这是由于若第一步向下走,就要一直向下走。
考虑如何转移
对于节点 $u$,考虑 $u$ 的所有子节点 $v$,用 $dp[0][v]$ 来更新 $dp[0][u]$, $dp[1][u]$ 。
至于 $dp[2][u]$ , 仍考虑两种情况:
(1)第二步向下走, 这样便转移到 $u$ 的父亲节点 $f$ 第一步向下走的情况。
这时还要考虑用 $dp[0][f]$ 还是 $dp[1][f]$ 来更新 $dp[2][u]$ :
如果从 $f$ 第一步走到 $u$ 能走出一条从 $f$ 向下的最长路,就用 $dp[1][f]$ 来更新 $dp[2][u]$ ,否则用 $dp[0][f]$ 。
(2)第二步仍向上走,这样便转移到 $f$ 第一步向上走的情况,即 $dp[2][f]$ 。

Implementation:
#include <bits/stdc++.h>
using namespace std;

const int N(1e4+5);
//dp[0][u]:u到其后代的最长路
//dp[1][u]:u到其后代的次长路
int dp[3][N];
typedef pair<int,int> E;
vector<E> g[N];
//第一步向下走(一直向下走)
void dfs1(int u, int f){
    dp[0][u]=dp[1][u]=0;
    for(int i=0; i<g[u].size(); i++){
        int &v=g[u][i].first, &c=g[u][i].second;
        if(v==f) continue;
        dfs1(v, u);
        if(dp[0][u]<dp[0][v]+c){
            //注意更新dp[0][u]和dp[1][u]的顺序
            dp[1][u]=dp[0][u];
            dp[0][u]=dp[0][v]+c;
        }
        else dp[1][u]=max(dp[1][u], dp[0][v]+c);
    }
}
//第一步向上走
void dfs2(int u, int f){
    for(int i=0; i<g[u].size(); i++){
        int &v=g[u][i].first, &c=g[u][i].second;
        if(v==f) continue;
        //第二步向下走
        dp[2][v]=0;
        if(dp[0][u]==dp[0][v]+c){
            dp[2][v]=max(dp[2][v], dp[1][u]+c);
        }
        else{
            dp[2][v]=max(dp[2][v], dp[0][u]+c);
        }
        //第二步向上走(转移到u的第一步向上走)
        dp[2][v]=max(dp[2][v], dp[2][u]+c);
        dfs2(v, u);
    }
}
int main(){
    for(int n; ~scanf("%d", &n);){
        for(int i=1; i<=n; ++i) g[i].clear();
        for(int u=2, v, c; u<=n; ++u){
            scanf("%d%d", &v, &c); 
            g[u].push_back({v, c});
            g[v].push_back({u, c});
        }
        dfs1(1, 1);
        dp[2][1]=0;
        dfs2(1, 1);
        for(int i=1; i<=n; i++)
            printf("%d\n", max(dp[0][i], dp[2][i]));
    }
}

 

posted @ 2015-10-13 08:53  Pat  阅读(362)  评论(0编辑  收藏  举报