【题目链接】
【算法】
我们知道,一棵树上离某个节点最远的节点,可能是经过它的祖先,再到那个祖先的某个孩子,或者,是它的那颗子树中,离它最远的一个节点,就不难想到以下算法 :
第一遍DFS,搜出每个节点的子树中离它距离最远的孩子的距离和所经过的儿子,离它次远的孩子的距离和所经过的儿子
第二遍DFS,树形DP求出每个点经过它的祖先节点的最远距离
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 10010 int i,n,x; int fa[MAXN],f[MAXN][2],g[MAXN][2],dp[MAXN]; vector< pair<int,int> > e[MAXN]; inline void init() { int i; memset(f,0,sizeof(f)); memset(dp,0,sizeof(dp)); for (i = 1; i <= n; i++) e[i].clear(); } inline void dfs1(int x) { int i,y; for (i = 0; i < e[x].size(); i++) { y = e[x][i].first; dfs1(y); if (f[y][0] + e[x][i].second >= f[x][0]) { f[x][1] = f[x][0]; g[x][1] = g[x][0]; f[x][0] = f[y][0] + e[x][i].second; g[x][0] = y; } else if (f[y][0] + e[x][i].second > f[x][1]) { f[x][1] = f[y][0] + e[x][i].second; g[x][1] = y; } } } inline void dfs2(int x) { int i,y; for (i = 0; i < e[x].size(); i++) { y = e[x][i].first; if (g[x][0] != y) dp[y] = max(dp[y],max(dp[x],f[x][0])+e[x][i].second); else dp[y] = max(dp[y],max(dp[x],f[x][1])+e[x][i].second); dfs2(y); } } int main() { while (scanf("%d",&n) != EOF) { init(); for (i = 2; i <= n; i++) { scanf("%d%d",&fa[i],&x); e[fa[i]].push_back(make_pair(i,x)); } dfs1(1); dfs2(1); for (i = 1; i <= n; i++) printf("%d\n",max(f[i][0],dp[i])); } return 0; }