首先简单的树形dp求祖宗到儿子的最长距离并记录最短距离是哪个儿子
此时对于每个点只维护了儿子到它的最短距离
还要记录祖宗到它的最短距离这时需要再跑一遍dfs把每个点与祖宗相关的到它的最长边搞出来
经典模型必须熟悉啊!!!!!!
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#define maxn 10005
#define LL long long
using namespace std;
LL dp[maxn][2], va[maxn * 2];
int Next[maxn * 2], last[maxn * 2], edge[maxn * 2], l;
int n;
void add(int a, int b, LL Va)
{
edge[l] = b;
va[l] = Va;
Next[l] = last[a];
last[a] = l;
l++;
}
void dfs(int pre)
{
dp[pre][0] = dp[pre][1] = 0;
for(int i = last[pre]; i!=-1 ; i = Next[i])
{
dfs(edge[i]);
if(dp[edge[i]][0] + va[i]> dp[pre][0])
{
dp[pre][0] = dp[edge[i]][0] + va[i];
dp[pre][1] = edge[i];
}
}
}
void dfs2(int pre, LL dis, int fa)
{
if(dis >= dp[pre][0])
{
dp[pre][0] = dis;
dp[pre][1] = fa;
}
LL Max = dis;
int sym = -1;
for(int i = last[pre]; i!=-1 ; i = Next[i])
{
if(edge[i] != dp[pre][1])
{
Max = max(Max, va[i] + dp[edge[i]][0]);
dfs2(edge[i], va[i] + dp[pre][0], pre);
}
else sym = i;
}
if(sym != -1) dfs2(dp[pre][1], Max + va[sym], pre);
}
int main()
{
while(scanf("%d", &n)!=EOF)
{
l = 0;
memset(last, -1 ,sizeof(last));
for(int i = 2; i<= n; i++)
{
int a;
LL va;
scanf("%d %I64d", &a, &va);
add(a, i, va);
}
dfs(1);
// for(int i = 1; i<= n; i++) printf("%I64d %I64d\n",dp[i][0], dp[i][1]);
dfs2(1, 0, 0);
for(int i = 1; i <= n; i++) printf("%I64d\n", dp[i][0]);
}
return 0;
}