1. 程式人生 > >HDU - 2196

HDU - 2196

ems while log pid blog 它的 nod ring 兩個

傳送門

求從樹上每一點出發能得到的最長路。

對於一個結點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\n", max(dp[i][1],dp[i][3])); 48 } 49 return 0; 50 }

HDU - 2196