题意:输入
n
n
n 个结点,然后输入
n
−
1
n-1
n−1 行,两个数字
u
u
u
w
w
w,表示,
i
i
i(第
i
i
i 行) 是
u
u
u 的子结点。求每个结点距离他最远的距离。(
1
1
1 号结点为根结点)
思路:
d
p
[
i
]
[
0
]
:
dp[i][0]:
dp[i][0]:结点
i
i
i 的子树到
i
i
i 的最长距离
d
p
[
i
]
[
1
]
:
dp[i][1]:
dp[i][1]:结点
i
i
i 的子树到
i
i
i 的次长距离
d
p
[
i
]
[
2
]
:
dp[i][2]:
dp[i][2]:从结点
i
i
i 往上走的最长距离
每个结点的最长和次长距离我们用
d
p
dp
dp 的方式自下而上的去更新(保证次长和最长分别分布在左右子树上),算出
d
p
[
i
]
[
0
]
dp[i][0]
dp[i][0] 和
d
p
[
i
]
[
1
]
dp[i][1]
dp[i][1] 后,如果要计算
u
u
u 的上面的最长距离,我们可以发现:
如果
u
u
u 不在其父亲的最长链上,那么距离他最长的距离就是
m
a
x
(
他
父
亲
往
上
走
的
最
长
距
离
,
他
父
亲
的
子
树
的
最
长
距
离
)
+
他
们
之
间
的
距
离
max(他父亲往上走的最长距离,他父亲的子树的最长距离) + 他们之间的距离
max(他父亲往上走的最长距离,他父亲的子树的最长距离)+他们之间的距离
如果
u
u
u 在其父亲的最长链上,那么距离他最长的距离就是
m
a
x
(
他
父
亲
往
上
走
的
最
长
距
离
,
他
父
亲
的
子
树
的
次
长
距
离
)
+
他
们
之
间
的
距
离
max(他父亲往上走的最长距离,他父亲的子树的次长距离) + 他们之间的距离
max(他父亲往上走的最长距离,他父亲的子树的次长距离)+他们之间的距离
上述语言符号化:
i
f
(
d
p
[
v
]
[
0
]
+
w
[
u
]
[
v
]
=
=
d
p
[
u
]
[
0
]
)
if(dp[v][0]+w[u][v]==dp[u][0])
if(dp[v][0]+w[u][v]==dp[u][0]) 儿子在父亲的最长链上
d
p
[
v
]
[
2
]
=
m
a
x
(
d
p
[
u
]
[
2
]
,
d
p
[
u
]
[
1
]
)
+
w
[
u
]
[
v
]
dp[v][2]=max(dp[u][2],dp[u][1]) + w[u][v]
dp[v][2]=max(dp[u][2],dp[u][1])+w[u][v]
e
l
s
e
else
else
d
p
[
v
]
[
2
]
=
m
a
x
(
d
p
[
u
]
[
2
]
,
d
p
[
u
]
[
0
]
)
+
w
[
u
]
[
v
]
dp[v][2]=max(dp[u][2],dp[u][0])+w[u][v]
dp[v][2]=max(dp[u][2],dp[u][0])+w[u][v] 儿子不在父亲的最长链上
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int Max_n = 1e4 + 10;
int head[Max_n], cnt;
ll dp[Max_n][3];
struct Edge {
int u, v, w, next;
} edge[Max_n << 1];
void addedge(int u, int v, int w) {
edge[cnt].u = u;
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void dfs1(int u) {
ll one = 0, two = 0;
for(int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].v;
dfs1(v);
ll cost = dp[v][0] + (ll)edge[i].w;
if(cost >= one) {
two = one;
one = cost;
}
if(cost < one && cost > two) {
two = cost;
}
}
dp[u][0] = one;
dp[u][1] = two;
}
void dfs2(int u) {
for(int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].v;
if(dp[v][0] + (ll)edge[i].w == dp[u][0])
dp[v][2] = max(dp[u][2], dp[u][1]) + (ll)edge[i].w;
else
dp[v][2] = max(dp[u][2], dp[u][0]) + (ll)edge[i].w;
dfs2(v);
}
}
int main() {
int n;
while(~scanf("%d", &n)) {
cnt = 0;
for(int i = 1; i <= n; i++)
head[i] = -1;
for(int i = 2; i <= n; i++) {
int u, w;
scanf("%d%d", &u, &w);
addedge(u, i, w); //i 是 u 的子结点
}
memset(dp, 0, sizeof(dp));
dfs1(1);
dfs2(1);
for(int i = 1; i <= n; i++)
printf("%lld\n", max(dp[i][0], dp[i][2]));
}
return 0;
}
/**
* Copyright(c)
* All rights reserved.
* Author : Max_n
* Date : 2019-10-07-21.39.43
* Problem : hdu 2196 Computer
*/