hdu 2196 Computer (树形dp)
链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2196
题目:
Computer
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.
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
题意:
给定一棵树,求每一个节点所能到达的最长路径的长度
思路:
以编号的i的节点为例(非根节点),最长的路径长度只有俩种可能,1)子树中(子节点方向)存在最长路径;2)通过父节点的路径中存在最长路径,所以,只有分别求出每一节点对应的那俩种路径取大最大值。
代码:
View Code
1 #include<stdio.h> 2 #include<string.h> 3 #include<vector> 4 #define N 10005 5 using namespace std; 6 7 struct point 8 { 9 int v; 10 int val; 11 }; 12 13 vector < point > Q[N]; 14 int n; 15 16 int far[N];// 该节点向 子节点 方向搜索的最远距离 17 int sfar[N];// ······················次远距离 18 int dir[N];// 在子节点方向搜到最远距离的那条边时,记录那条边上距离该点最近的那个位置(点) 19 int dp[N];// 记录从 父节点 方向搜的最远距离 20 21 void pp() 22 { 23 memset(dir,0,sizeof(dir)); 24 memset(dp,0,sizeof(dp)); 25 memset(far,0,sizeof(far)); 26 memset(sfar,0,sizeof(sfar)); 27 for(int i=1;i<=n;i++) 28 Q[i].clear(); 29 } 30 31 /*求子节点方向的最长距离 32 由下往上递推 ,先dfs 后处理*/ 33 34 void dfs1(int root) //找子节点方向的最长距离与次远距离 35 { 36 int flag1=-1; 37 38 int flag2=-1,max=-1,i,size; 39 size=Q[root].size(); 40 41 if(far[root]||size==0) return ; 42 43 for(i=0;i<size;i++) 44 { 45 int k=Q[root][i].v; 46 47 dfs1(k); 48 if(max<far[k]+Q[root][i].val)//找最远距离 49 { 50 max=far[k]+Q[root][i].val; 51 flag1=i; //记录在子节点方向搜到最远距离的那条边时,挨着root点的那个点(最后赋值到dir【root】中) 52 } 53 } 54 dir[root]=flag1; 55 far[root]=max; 56 max=-1; 57 58 for(i=0;i<size;i++) 59 { 60 int k=Q[root][i].v; //子节点 61 62 if(i!=flag1&&max<far[k]+Q[root][i].val)//找次远距离 (不能是最远距离那条边) 63 { 64 max=far[k]+Q[root][i].val; 65 flag2=i; 66 } 67 } 68 if(flag2!=-1) sfar[root]=max; 69 } 70 71 /* 72 由上往下 推 先处理后 dfs*/ 73 74 void dfs2(int root) //找父节点方向的最远距离 75 { 76 int i,size; 77 size=Q[root].size(); 78 79 if(size==0) return ; 80 81 for(i=0;i<size;i++) 82 { 83 int k=Q[root][i].v; //子节点 84 85 //判断该点是否在父节点的最远距离 的那条边上 86 87 //((i==dir[root]用i不用k)) 88 89 if(i==dir[root]) //如果在 则用父节点root的次远距离 “ sfar【root】 ” 与root的父节点方向的最远距离 dp【root】比较 90 dp[k]=max(sfar[root],dp[root])+Q[root][i].val; 91 92 else //如果不在 则用父节点root的最远距离 " far【root】 ”与root的父节点方向的最远距离 dp【root】比较 93 dp[k]=max(far[root],dp[root])+Q[root][i].val; 94 95 // Q[root][i].val=====子节点与父节点直接的距离((Q[root][i].val 用i不用k)) 96 97 dfs2(k); 98 } 99 } 100 int main() 101 { 102 point t; 103 while(scanf("%d",&n)!=EOF) 104 { 105 int i,a,b; 106 pp(); 107 for(i=2;i<=n;i++) 108 { 109 scanf("%d %d",&a,&b); 110 t.val=b; 111 /***/ t.v=i; 112 Q[a].push_back(t); //把它存成一个有向图 113 } 114 115 dfs1(1); 116 dfs2(1); 117 118 for(i=1;i<=n;i++) //从子节点与父节点方向取一个最远的距离 119 printf("%d\n",max(far[i],dp[i])); 120 } 121 }