hdu2196

电脑

题目描述:

水题,一棵树,每个节点的最远距离

题解:

树形dp,先跑出来dpm和dps,然后再dfs,参数含fa的去掉儿子的len,之后比较找出当前u的结果以及u的去掉儿子的len,传下去

重点:

标准的u去掉儿子的len以及求u的最远距离

代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(int i = a;i < b;i++)
#define REP_D(i, a, b) for(int i = a;i <= b;i++)

typedef long long ll;

using namespace std;

const int maxn = 1e4 +100;
struct info
{
    int to, len;
};
vector<info> G[maxn];
int n, dpm[maxn], dps[maxn];
int s[maxn];
void dfs_s(int u, int fa, int fa_l, int fa_len)//fa_len是fa到u的长度.fa_l是fa的去掉儿子的长度.
{
    int l = 0;
    if(fa == 0)//第一次
    {
        l = 0;
        s[u] = dpm[u];
        REP(i, 0, G[u].size())
        {
            int v = G[u][i].to, len = G[u][i].len;
            if(v!=fa)
            {
                dfs_s(v, u, l, len);
            }
        }
    }
    else
    {
        l = fa_l;
        if(dpm[fa]==fa_len+dpm[u])//先搞出fa带上不是u的儿子的最长链
        {
            l = max(l, dps[fa]);
        }
        else
        {
            l = max(l, dpm[fa]);
        }
        l += fa_len;//u不带儿子的最长链
        s[u] = max(dpm[u], l);//结果
        REP(i, 0, G[u].size())
        {
            int v = G[u][i].to, len = G[u][i].len;
            if(v!=fa)
            {
                dfs_s(v, u, l, len);
            }
        }
    }

}
void dfs(int u, int fa)//正常的,找出dpm和dps
{
    dpm[u] = dps[u] = 0;
    REP(i, 0, G[u].size())
    {
        int v = G[u][i].to, len = G[u][i].len;
        if(v!=fa)
        {
            dfs(v, u);
            int t = dpm[v] + len;//只用每一个儿子的最长来更新就好.
            if(t > dpm[u])
            {
                dps[u] = dpm[u];
                dpm[u] = t;
            }
            else if(t > dps[u])
            {
                dps[u] = t;
            }
        }
    }
}

void solve()
{
    dfs(1, 0);
    dfs_s(1, 0, 0, 0);
    REP_D(i, 1, n)
    {
        printf("%d\n", s[i]);
    }
}
int main()
{
   // freopen("1Ain.txt", "r", stdin);
    //freopen("1Aout.txt", "w", stdout);
    while(scanf("%d", &n) != EOF)
    {
        REP_D(i, 1, n)
        {
            G[i].clear();
        }
        REP_D(i, 2, n)
        {
            int b, len;
            scanf("%d%d", &b, &len);
            info t;
            t.to = b;
            t.len = len;
            G[i].push_back(t);
            t.to = i;
            G[b].push_back(t);
        }
        solve();
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值