树形dp

HDU 2196
题意:给一颗树,求出每个点到其距离最远的点的距离。
输入是,行的编号的点到第一个值的点的距离是第三个点的值;行的编号是从2开始的;
思路:每一个点距离其他点的最大距离只有可能来自两个方向,1是来自以改点为根的子树上,2是来自其父节点;但是有可能其父节点的第一种情况就是来自这个点(比如u->v,以u为根的子树上的最远距离来自以v节点为根的子树),所以在统计第一种情况是要统计最大值还有次大值,发生上述情况后用次大值就可达到最优解;

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct zp
{
    int u,v,w,Next;
} node[10010];
int head[20010],cont;
int dp[10010][3];//0以该节点为根节点的最大值     1次大值     2来自父节点的最优解
void init()
{
    memset(head,-1,sizeof(head));
    memset(dp,0,sizeof(dp));
    cont=0;
}
void dfs1(int u)//得出dp0和1的值
{
    int maxn=0,smaxn=0;
    for(int i=head[u];i!=-1;i=node[i].Next)
    {
        int v=node[i].v;
        dfs1(v);
        smaxn=max(smaxn,dp[v][0]+node[i].w);
        if(smaxn>maxn)
            swap(smaxn,maxn);
    }
    dp[u][0]=maxn;
    dp[u][1]=smaxn;
}
void dfs2(int u)//得出dp2的值
{
    for(int i=head[u];i!=-1;i=node[i].Next)
    {
        int v=node[i].v;
        dp[v][2]=max(dp[u][2],dp[v][0]+node[i].w==dp[u][0]?dp[u][1]:dp[u][0])+node[i].w;//如果dp[v][0]+node[i].w==dp[u][0]则说明发生了上面提到的那种情况
        dfs2(v);
    }
}
void add_edge(int a,int b,int w)
{
    node[cont].u=b,node[cont].v=a,node[cont].w=w;
    node[cont].Next=head[b];
    head[b]=cont++;
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        init();
        for(int i=2;i<=n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add_edge(i,a,b);
        }
        dfs1(1);
        dp[1][2]=0;
        dfs2(1);
        for(int i=1;i<=n;i++)
            printf("%d\n",max(dp[i][0],dp[i][2]));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值