HDU 2196 树形dp入门

链接 : 传送门

题意: 给你一个n个节点的棵树,然后给你和 第i台电脑与第a台电脑相连的花费 v 问你最长的线路是多长(求树上任意节点所能达到的最远点的距离)

树形dp ,开个数组 分别记录这个点到子树最远节点的最长距离次长距离 和记录到父节点上的最长距离 这样在树上dp
1. 求子树最长次长
       dp[u][0] =max(dp[u][0],dfs(v,u)+val) 子树最长距离 =max(子树节点到子树的子树的最远距离 + 子树到根的距离 , 子树最长距离);
   a. 最长更新
      dp[u][1] =max(dp[u][1],dp[u][0])
   b. 最长不更新
    dp[u][1]=max(dp[u][1],dfs(v,u)+val)
2.求父节点 最长
  a. 如果父节点最长子树通过该节点,则父节点最长等于父节点次长加到子节点的距离或者父节点在其父节点的最长加到子节点的距离
    dp[v][2]=max(dp[u][2]+val,dp[u][1]+val)
  b. 如果不通过那就是父节点最长等于父节点最长加到子节点的距离或者父节点在其父节点的最长加到子节点的距离
    dp[v][2]=max(dp[u][2]+val,dp[u][0]+val)


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rd(a) scanf("%d",&a)
#define rlld(a) scanf("%lld",&a)
#define me(a,b) memset(a,b,sizeof(a))
const int inf= 0x3f3f3f3f;
const int maxn=1e4 + 3;
const ll mod =1e9+7;
int dist[maxn][3];
struct node{
    int next,v,val;
}ss[maxn*2];
int head[maxn];
int pre[maxn];
int cnt=0;
inline void add(int u,int v,int val){

    ss[cnt].v=v;
    ss[cnt].val=val;
    ss[cnt].next=head[u];
    head[u]=cnt++;


}
inline void init (){
    cnt=0;
    me(head,-1);
    me(dist,0);
    me(pre,-1);

}
int dfs(int u,int fa)
{

    for(int i=head[u];~i;i=ss[i].next){
        int v=ss[i].v;
        int val=ss[i].val;
        if(v==fa) continue;
        int ans=dfs(v,u);   
        if(ans+val>=dist[u][0]){
            dist[u][1]=max(dist[u][0],dist[u][1]);
            dist[u][0]=ans+val;
            pre[u]=v;
        }
        else{
            dist[u][1]=max(dist[u][1],ans+val);
        }

    }
    return dist[u][0];

}
void dfs1(int u,int fa){

    for(int i=head[u];~i;i=ss[i].next){

        int v=ss[i].v;
        int val=ss[i].val;
        if(v==fa) continue;
        if(pre[u]==v) dist[v][2]=max(dist[u][2]+val,dist[u][1]+val); 
        else dist[v][2]=max(dist[u][0]+val,dist[u][2]+val);
        dfs1(v,u);
    }


}
int main(){

    int n;
    while(cin>>n){
        init();
        for(int i=2;i<=n;i++) 
        {
            int v,val;
            cin>>v>>val;
            add(v,i,val);
            add(i,v,val);
        }
        dfs(1,-1);
        dfs1(1,-1);
        for(int i=1;i<=n;i++) cout<< max(dist[i][0],dist[i][2])<<endl;

    }




    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值