杭电 HDU 2196 Computer Time (树形dp)

来源:互联网 发布:udp端口在线扫描 编辑:程序博客网 时间:2024/05/17 22:16

Computer

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


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
51 12 13 11 1
 

Sample Output
32344
 

Author
scnu
 

Recommend
lcy   |   We have carefully selected several similar problems for you:  1561 1011 3456 1520 2242

 借用http://blog.csdn.net/shuangde800/article/details/9732825一个图:



题意:首先给定编号为1的电脑,对于读入图的时候,注意给出的第 i  对整数x1,  x2,代表将第二台电脑接到
x1的后面,缆线长为x2。并且注意到图的根一定为1,因为都是在1后面依次往后接的。然后要求我们求的是对于
每一个点能够沿着线路所能走的最长距离。
思路:
以图中点4为例,4的最长路来源有两个方向,一个是其子树方向(即)往下的最长路,另一种可能是最长路来自父节点,或着说经过父节点到达4结点。对于其子树方向的最长路,我们可以一次dfs正常求出。对于第二种等于2结点的来自父节点的最长路或着来自子树方向的次最长路加上dis(2,4)即可。
我在程序中的数据结构:
A数组:                  记录V结点沿子树方向最长路所经过V的孩子编号。
B数组:                  记录沿子树方向的次长路长度。
dp1数组:              记录子树方向的最长路。
dp2数组:              记录来自父节点的最长路。
vector<PLL>cnt:记录每条边的信息。
我们假设一个结点V的孩子为{v1,v2,v3……vn};
1. 如果vi在V沿子树方向的最长路上
那么dis【vi】 = max(dp1【vi】,max(dp2【V】,B【V】) + dis(V,vi))
   说一下内嵌的max,以图中2(V)结点2结点来自父节点的最长路和2结点的子树方向次长路的较大值加上V 和vi的距离

2.   如果vi不在V沿子树方向的最长路上
 那么dis【vi】= max(dp1【V】,dp2【V】) + dis(V, vi);
最长路要么来自父节点子树方向的最长路加上dis(V,vi),要不来自父节点V的从V的父节点来的最长路 + dis(V,  vi);

对于根节点特殊处理因为没有父节点只有次最长路,并且单孩子的结点没有次长路。
是时候贴一下代码了:
/*=============================================================================##      Author: liangshu - cbam ##      QQ : 756029571 ##      School : 哈尔滨理工大学 ##      Last modified: 2015-09-03 09:04##     Filename: H.cpp##     Description: #        The people who are crazy enough to think they can change the world, are the ones who do ! =============================================================================*/##include<iostream>#include<sstream>#include<algorithm>#include<cstdio>#include<string.h>#include<cctype>#include<string>#include<cmath>#include<vector>#include<stack>#include<queue>#include<map>#include<set>using namespace std;const int INF = 10001;int n, A[INF], B[INF], dp1[INF],dp2[INF];typedef pair<int, int> PLL;vector<PLL>cnt[INF];int dfs1(int root){    int len = cnt[root].size();    if(!len){//搜索到叶子        return 0;    }    int Max = -1, loc1 = -1, loc2 = -1;    for(int i = 0; i < len; i++){//寻找最长路        if(dfs1(cnt[root][i].first) + cnt[root][i].second > Max){            Max = dfs1(cnt[root][i].first) + cnt[root][i].second;            loc1 = i;        }    }    dp1[root] = Max;    Max = -1;    A[root] = loc1;    for(int i = 0; i < len; i++){//寻找次长路        if(dp1[cnt[root][i].first] + cnt[root][i].second > Max && i != loc1){            Max = dp1[cnt[root][i].first] +cnt[root][i].second;            loc2 = i;        }        if(loc2 != -1)B[root] = Max;    }    return dp1[root];}void dfs2(int root){    int len = cnt[root].size();    for(int i = 0; i < len; i++){        if(i == A[root]){//这个孩子在沿子树方向的最长路径上            dp2[cnt[root][i].first] = max(dp2[root], B[root]) + cnt[root][i].second;        }        else{            dp2[cnt[root][i].first] = max(dp2[root], dp1[root]) + cnt[root][i].second;        }        dfs2(cnt[root][i].first);    }}int main(){    while(scanf("%d",&n) != EOF){      memset(dp1, 0, sizeof(dp1));      memset(B, 0, sizeof(B));      memset(A, 0, sizeof(A));      memset(dp2, 0, sizeof(dp2));      for(int i = 1; i <= INF; i++){          cnt[i].clear();      }      for(int i = 2; i <= n; i++){          int x1, x2;           scanf("%d%d", &x1, &x2);           cnt[x1].push_back(make_pair(i, x2));      }      dfs1(1);      dfs2(1);      for(int i = 1; i <= n; i++){        cout<<max(dp1[i], dp2[i])<<endl;      }    }    return 0;}


0 0
原创粉丝点击