hdu 3534 Tree(树形dp)

7 篇文章 0 订阅

裸树形dp

#include <STDIO.H>
#include <STRING.H>
const int MAXN = 50000;
struct node
{
    int to, next, val;
}edge[MAXN*2];
int head[MAXN];
int tol;
int fst_max[MAXN];
int sec_max[MAXN];
int fst_num[MAXN];
int sec_num[MAXN];
int path[MAXN];    //该结点为根的子树中,包含该结点的最长路径长度
int num[MAXN];    //最长路径的长度

void add(int u, int v, int w)
{
    edge[tol].to = v;
    edge[tol].val = w;
    edge[tol].next = head[u];
    head[u] = tol++;
    edge[tol].to = u;
    edge[tol].val = w;
    edge[tol].next = head[v];
    head[v] = tol++;
}

// 保留一个根节点,其余端节点作为叶子节点
void dfs(int u, int pre)
{
    fst_max[u] = sec_max[u] = 0;
    fst_num[u] = sec_num[u] = 0;
    int i, j;
    for (i = head[u]; i != -1; i = edge[i].next)
    {
        int v = edge[i].to;
        if (v == pre) continue;
        dfs(v, u);
        if (fst_max[v] + edge[i].val > fst_max[u])
        {
            sec_max[u] = fst_max[u];
            sec_num[u] = fst_num[u];
            fst_max[u] = fst_max[v] + edge[i].val;
            fst_num[u] = fst_num[v];
        }
        else if (fst_max[v] + edge[i].val == fst_max[u])
        {
            fst_num[u] += fst_num[v];
        }
        else if (fst_max[v] + edge[i].val > sec_max[u])
        {
            sec_max[u] = fst_max[v] + edge[i].val;
            sec_num[u] = fst_num[v];
        }
        else if (fst_max[v] + edge[i].val == sec_max[u])
        {
            sec_num[u] += fst_num[v];
        }
    }

    if (fst_num[u] == 0)    // leaf node
    {
        fst_max[u] = sec_max[u] = 0;
        fst_num[u] = sec_num[u] = 1;
        path[u] = 0;
        num[u] = 1;
        return ;
    }
    int c1 = 0, c2 = 0;
    path[u] = num[u] = 0;
    for (i = head[u]; i != -1; i = edge[i].next)
    {
        int v = edge[i].to;
        if (v == pre) continue;
        if (fst_max[u] == fst_max[v] + edge[i].val)
            c1++;
        else if (sec_max[u] == fst_max[v] + edge[i].val)
            c2++;
    }
    if (c1 >= 2)    // first + first
    {
        int tmp = 0;
        path[u] = fst_max[u]*2;
        for (j = head[u]; j != -1; j = edge[j].next)
        {
            int v = edge[j].to;
            if (v == pre) continue;
            if (fst_max[u] == fst_max[v] + edge[j].val)
            {
                num[u] += tmp * fst_num[v];
                tmp += fst_num[v];
            }
        }
    }
    else if (c1 >= 1 && c2 >= 1)
    {
        path[u] = fst_max[u] + sec_max[u];
        for (i = head[u]; i!= -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if (v== pre) continue;
            if (fst_max[u] == fst_max[v] + edge[i].val)
            {
                num[u] += fst_num[v] * sec_num[u];
            }
        }
    }
    else
    {
        path[u] = fst_max[u];
        num[u] = fst_num[u];
    }
}
int main()   
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int n;
    int i;
    while (scanf("%d", &n) == 1)
    {
        int u, v, w;
        tol = 0;
        memset(head, -1, sizeof head);
        for (i = 1; i< n; ++i)
        {
            scanf("%d%d%d", &u, &v, &w);
            add(u, v, w);
        }
        dfs(1, -1);
        int ans1 = 0, ans2 = 0;
        for (i = 1; i<= n; ++i)
        {
            if (path[i] > ans1)
            {
                ans1 = path[i];
                ans2 = num[i];
            }
            else if (path[i] == ans1)
            {
                ans2 += num[i];
            }
        }
        printf("%d %d\n", ans1, ans2);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值