最长链(length)
【题目描述】
给定一棵有 N 个节点的树,求每个节点到其他节点的最大距离
【输入格式】
输入第一行是一个自然数 N (N<=10000), 接下来(N-1) 行描述:
第i 行包含两个自然数, 表示编号为i 的节点连接到的节点编号和这条网线的长度..距离
总长不会超过10^9. 每行中的两个数字用空格隔开.
【输出格式】
输出包含 N 行. 第 i 行表示对于离编号为 i 的节点最远的节点与该节点的距离 Si
(1<=i<=N).
【样例输入】length.in
3
1 1
1 2
【样例输出】length.out
2
3
3
【数据范围】
30% N<=100
100%N<=10000
分析:
这道题由于数据范围有限,
又符合树的结构特征,可以用dfs来做,
3遍dfs出解。
View Code
1 program length;
2 var
3 i,ww,j,n,m,k,w,mm,t:Longint;
4 x,y,z:longint;
5 a,ll:array[1..10010,1..500]of longint;
6 d1,d2,l,v:array[0..10010]of longint;
7 //a记录的是边的长度
8 //ll记录的是边连接的点的编号
9 procedure dfs(x,dis:longint);
10 var
11 i,j,bb:longint;
12 begin
13 bb:=0;v[x]:=1;
14 for i:=1 to l[x] do
15 if (v[ll[x,i]]=0) then
16 begin
17 bb:=1;
18 dfs(ll[x,i],dis+a[x,i]);
19 end;
20
21 if (bb=0)and(dis>m) then begin w:=x;m:=dis;end;
22 end;
23 //第一遍dfs,从任意一点(我选取的是1号点)出发,
24 //找到离该点最远的点
25
26 procedure dfss(x,dis:longint);
27 var
28 i,j,bb:longint;
29 begin
30 d1[x]:=dis;
31 bb:=0;v[x]:=1;
32 for i:=1 to l[x] do
33 if v[ll[x,i]]=0 then
34 begin
35 bb:=1;
36 dfss(ll[x,i],dis+a[x,i]);
37 end;
38
39 if (bb=0)and(dis>m) then begin w:=x;m:=dis;end;
40 end;
41 //第二遍dfs
42 //找到树的直径(即树中距离最远的两点)
43 //与tyvj中“树的直径”一题相同(那道题只需两遍dfs)
44
45 procedure dfsss(x,dis:longint);
46 var
47 i,j,bb:longint;
48 begin
49 d2[x]:=dis;
50 bb:=0;v[x]:=1;
51 for i:=1 to l[x] do
52 if v[ll[x,i]]=0 then
53 begin
54 bb:=1;
55 dfsss(ll[x,i],dis+a[x,i]);
56 end;
57 end;
58 //第三遍dfs
59 //找到树直径另一端点到树中各点的距离
60
61 function max(x,y:longint):longint;
62 begin
63 if x>=y then exit(x)
64 else exit(y);
65 end;
66
67 begin
68 assign(input,'length.in');
69 reset(input);
70 assign(output,'length.out');
71 rewrite(output);
72 readln(n);
73 for i:=2 to n do
74 begin
75 readln(x,y);
76 inc(l[i]); a[i,l[i]]:=y; ll[i,l[i]]:=x;
77 inc(l[x]); a[x,l[x]]:=y; ll[x,l[x]]:=i;
78 end;
79 //使用伪矩阵方法读入(部分空间浪费,但比纯矩阵要节省空间,因为树的边有限,一般也没有极限数据卡这个)
80 //注:纯矩阵存储超内存,我不会链表,只好这样存
81
82 fillchar(v,sizeof(v),0);
83 m:=0;
84 dfs(1,0);
85
86 fillchar(v,sizeof(v),0);
87 mm:=m;m:=0;
88 ww:=w;
89 dfss(ww,0);
90 //求出直径,w和ww分别为两端点
91
92 fillchar(v,sizeof(v),0);
93 dfsss(w,0);
94
95 for i:=1 to n do writeln(max(d1[i],d2[i]));
96 //树中任意点能达到的最远距离一定是两端点之一,易证得
97 close(input);
98 close(output);
99 end.