hdoj 2196 Computer 树形dp经典题

首先简单的树形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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值