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
5
1 1
2 1
3 1
1 1
Sample Output
3
2
3
4
4
个人理解
我们处理一个根到这棵树所有节点的最长路径容易处理,然后拿到这个题我第一反应就是:那就让每个点作为根跑一边最基本自底向上的树形dp不就可以了,不出意外,TLE了。然后就猜这个题肯定是按照一个点为根跑一遍树形dp,然后再进行一系列的操作,得出来所有的为根的最远距离。
我们想哈,当你跑第一遍树形dp时候,从父节点走到这个子节点的时候,会继续求出以这个子节点为根的子树的最远距离,那么他就只能往他的子节点方向跑了。那如果离这个子节点最远的那个点在他的父节点方向上怎么办呢,我们可以让他往他的父节点跑就可以了,但是如果再以他的父节点为根跑下一层dfs的时候又会跑回这个点。
所以我们用f[i]和g[i]分别记录,第i个节点往儿子节点方向和往他父亲节点方向的最远距离,跑两次dfs,分别处理这两个数组的值。递推关系如下:
f
[
u
]
=
m
a
x
(
f
[
v
]
,
w
(
u
,
v
)
)
f[u] = max(f[v],w(u,v))
f[u]=max(f[v],w(u,v))
g
[
u
]
=
w
(
u
,
p
[
u
]
)
+
m
a
x
(
g
[
p
[
u
]
]
,
f
[
v
]
+
w
(
p
[
u
]
,
v
)
)
(
p
[
u
]
是
u
的
父
亲
,
v
是
p
[
u
]
的
儿
子
,
v
≠
u
)
g[u] = w(u,p[u])+max(g[p[u]],f[v]+w(p[u],v))(p[u]是u的父亲,v是p[u]的儿子,v \neq u)
g[u]=w(u,p[u])+max(g[p[u]],f[v]+w(p[u],v))(p[u]是u的父亲,v是p[u]的儿子,v̸=u)
代码
#include <bits/stdc++.h>
using namespace std;
inline int read() {int x=0;char p=getchar();while(p<'0'||p>'9')p=getchar();while(p>='0'&&p<='9')x=x*10+p-'0',p=getchar();return x;}
const int maxn = 10010;
struct node{
int to;
int w;
int next;
}edge[maxn<<1];
int cnt,head[maxn];
int f[maxn],g[maxn],p[maxn];
int n;
void init(){
cnt = 0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w){
edge[cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt++;
}
int dfs(int cur,int pre){
f[cur] = 0;
for(int i = head[cur];i!=-1;i = edge[i].next){
if(edge[i].to != pre){
p[edge[i].to] = cur;
f[cur] = max(f[cur],dfs(edge[i].to,cur)+edge[i].w);
}
}
return f[cur];
}
void dfs1(int cur,int pre){
int t = 0;
g[cur] = g[pre];
for(int i = head[pre];i!=-1;i = edge[i].next){
int v = edge[i].to;
if(v == p[pre]) continue;
if(v == cur){
t = edge[i].w;
}else{
g[cur] = max(g[cur],f[v]+edge[i].w);
}
}
g[cur]+=t;
for(int i = head[cur];i!=-1;i = edge[i].next){
if(edge[i].to!=pre){
dfs1(edge[i].to,cur);
}
}
}
int main(){
while(~scanf("%d",&n)){
init();
for(int u = 2;u<=n;u++){
int v,w;
v = read();
w = read();
add(u,v,w);
add(v,u,w);
}
dfs(1,0);dfs1(1,0);
for(int i = 1;i<=n;i++){
printf("%d\n",max(f[i],g[i]));
}
}
return 0;
}