HDOJ 2196 Computer

树形DP。求最长单链。用一种把自己也绕糊涂的方式做出来了- -!首先以第一台电脑为根节点,记录每个节点到每个子节点所属子孙节点中最长的距离。再求出除自己及自己子孙节点外到自己最长的距离。最后输出到自己子孙节点与到其他节点中最长的即可。

在求每个节点子节点最大值时,也要求出次大值,并记录最大值的下标,在求与其他节点最长距离时要用。

PS:在更新到子孙节点最大距离时,记得更新次大值。一开始在这里错了。调试时一开始以为是子节点数开小了。但是实际上开小了不是WA而是RE。而且刚开始还开大了,超内存,每个节点100个子节点足矣。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
struct Node
{
    int par;
    int son[105];//足矣
    int num;
    int mson[105];
    int len;
    int mx;
    int mx_;
    int mx2;
    int ft;
}a[10005];
void init(int n)
{
    for(int i=0;i<=n;i++)
    {
        a[i].par=i;
        a[i].num=0;
        a[i].len=0;
        a[i].mx=0;
        a[i].mx_=0;
        a[i].mx2=0;
        a[i].ft=0;
    }
}
int v[10005];
int dfs(int x)
{
    if(v[x]!=0)return a[x].mx;
    for(int i=0;i<a[x].num;i++)
    {
        a[x].mson[i]=dfs(a[x].son[i])+a[a[x].son[i]].len;
        if(a[x].mson[i]>a[x].mx)
        {
            if(a[x].mx!=0)
            {
                a[x].mx2=a[x].mx;
            }
            a[x].mx=a[x].mson[i];
            a[x].mx_=a[x].son[i];
        }
        else if(a[x].mson[i]>a[x].mx2){a[x].mx2=a[x].mson[i];}
    }
    v[x]=1;
    return a[x].mx;
}
int Ft(int x)
{
    if(v[x])return a[x].ft;
    v[x]=1;
    int xx=Ft(a[x].par);
    if(a[a[x].par].mx>xx)
    {
        if(a[a[x].par].mx_!=x)a[x].ft=a[a[x].par].mx;
        else
        {
            if(a[a[x].par].mx2>xx){a[x].ft=a[a[x].par].mx2;}
            else a[x].ft=xx;
        }
    }
    else a[x].ft=xx;
    a[x].ft+=a[x].len;
    return a[x].ft;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(v,0,sizeof(v));
        init(n);
        int x,y;
        for(int i=2;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            a[i].par=x;
            a[x].son[a[x].num]=i;
            a[i].len=y;
            a[x].num++;
        }
        dfs(1);
        memset(v,0,sizeof(v));
        v[1]=1;
        for(int i=2;i<=n;i++)
        {
            Ft(i);
        }
        for(int i=1;i<=n;i++)
        {
            printf("%d\n",max(a[i].ft,a[i].mx));
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值