HDU

传送门

求从树上每一点出发能得到的最长路。

对于一个结点node,从它出发的最长路要么是它向子树走能得到的最大值,要么是先走向parent,再加上parent的不经过node的最长路的值。此时parent有可能走向它的父亲,或者走向node的兄弟结点。所以每个点我们要记录向子树走的最长路dp[node][1]和次长路dp[node][2],还要记录经过其父亲结点的最长路dp[node][3]。

前两个可以在一次dfs中处理出,最后再用一次dfs求出经过父亲的最长路

 1 #include <vector>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int maxn = 1e4 + 10;
 8 int N;
 9 int dp[maxn][4];
10 vector<int> tree[maxn];
11 
12 void dfs1(int par) {
13     int fir = 0, sec = 0;
14     for (int i = 0; i < tree[par].size(); i++) {
15         int v = tree[par][i];
16         dfs1(v);
17         int tmp = dp[v][1] + dp[v][0];
18         if (tmp >= fir) {
19             sec = fir; fir = tmp;
20         } else if (tmp > sec) {
21             sec = tmp;
22         }
23     }
24     dp[par][1] = fir; dp[par][2] = sec;
25 }
26 
27 void dfs2(int par) {
28     for (int i = 0; i < tree[par].size(); i++) {
29         int v = tree[par][i];
30         dp[v][3] = dp[v][0] + max(dp[par][3],
31                                     (dp[v][0] + dp[v][1] == dp[par][1] ? dp[par][2] : dp[par][1]));
32         dfs2(v);
33     }
34 }
35 
36 int main() {
37     while (~scanf("%d", &N)) {
38         memset(dp, 0, sizeof(dp));
39         for (int i = 0; i <= N; i++) tree[i].clear();
40         for (int i = 2; i <= N; i++) {
41             int u;
42             scanf("%d%d", &u, &dp[i][0]);
43             tree[u].push_back(i);
44         }
45         dfs1(1);
46         dfs2(1);
47         for (int i = 1; i <= N; i++) printf("%d
", max(dp[i][1],dp[i][3]));
48     }
49     return 0;
50 }
原文地址:https://www.cnblogs.com/xFANx/p/7494993.html