【题意】:给出一棵树,求离每个节点最远的点的距离。
【题解】:经典的树dp,两次dfs即可。
第一次dfs把无向树变成有向树,并且求出每个节点到他子孙的最远距离。 down[]
第二次dfs求出每个节点经过其父亲结点到其他点的最远距离。 up[]
最后ans[i] = max(down[i], up[i]);
rec[i][0] 记录哪个子孙到结点i的距离最大
rec[i][1] 记录哪个子孙到结点i的距离次大
【代码】:
1 #include "iostream"
2 #include "cstdio"
3 #include "cstring"
4 #include "vector"
5 using namespace std;
6 #define pb push_back
7 #define maxn 10050
8 int n;
9 int down[maxn], up[maxn];
10 int rec[maxn][2], edge[maxn];
11 struct Edge {
12 int v, w;
13 Edge(){}
14 Edge(int _v, int _w) {
15 v = _v, w = _w;
16 }
17 };
18 vector<Edge> g[maxn];
19
20 void dfs1(int u, int fa) {
21 down[u] = 0;
22 rec[u][0] = rec[u][1] = -1;
23 int size = g[u].size();
24 for(int i = 0; i < size; i++) {
25 int v = g[u][i].v, w = g[u][i].w;
26 if(v == fa) continue;
27 dfs1(v, u);
28 edge[v] = w;
29 if(down[v] + w >= down[u]) {
30 down[u] = down[v] + w;
31 rec[u][1] = rec[u][0];
32 rec[u][0] = v;
33 } else if(rec[u][1] == -1 || down[v] + w > down[rec[u][1]] + edge[rec[u][1]]) rec[u][1] = v;
34 }
35 }
36
37 void dfs2(int u, int fa) {
38 up[u] = 0;
39 if(fa != -1) {
40 if(u == rec[fa][0]) {
41 up[u] = up[fa] + edge[u];
42 if(rec[fa][1] != -1) up[u] = max(up[u], down[rec[fa][1]] + edge[rec[fa][1]] + edge[u]);
43 } else up[u] = max(up[fa], down[fa]) + edge[u];
44 }
45 int size = g[u].size();
46 for(int i = 0; i < size; i++) {
47 int v = g[u][i].v;
48 if(v == fa) continue;
49 dfs2(v, u);
50 }
51 }
52
53 int main() {
54 int v, w;
55 while(~scanf("%d", &n)) {
56 for(int i = 0; i < maxn; i++) g[i].clear();
57 for(int i = 2; i <= n; i++) {
58 scanf("%d%d", &v, &w);
59 g[i].pb(Edge(v, w));
60 g[v].pb(Edge(i, w));
61 }
62 dfs1(1, -1);
63 dfs2(1, -1);
64 for(int i = 1; i <= n; i++) printf("%d\n", max(up[i], down[i]));
65 }
66 return 0;
67 }
68