hdoj 2196 Computer 樹形dp經典題
阿新 • • 發佈:2019-01-22
首先簡單的樹形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;
}