HDU 2196 Computer(树形dp)

题目大意: 求树中每个点到所有叶子节点的距离的最大值是多少。

思路: 这个题用两边dfs就可以,一遍是求当前点到子树那个方向上的最大值和次大值,另外一遍是父亲方向上的最大值。之所以要求子树方向上的次大值,是因为如果求当前点v的最长的距离的时候,子树里面的显而易见可以求出来,但是父亲方向上的就不确定了,如果父亲的取最大值的路径经过点v,那么这样求肯定就不对了,所以要求一个次大值,这时,用父亲的次大值加上父亲的权值和子树方向上的比较就行了。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 11000;
struct Edge {
    int to, Next, len;
};
Edge edge[maxn * 2];
int tot, head[maxn];
int maxlen[maxn], smaxlen[maxn];//maxlen当前节点的子树的最大值 smaxlen次大值 
int maxid[maxn], smaxid[maxn];//maxid当前节点取最大值时都应的儿子编号,  smaxid次大值时对应的编号 
void init()
{
    memset(head, -1, sizeof(head));
    tot = 0;
}
void addedge(int u, int v, int len)
{
    edge[tot].to = v;
    edge[tot].len = len;
    edge[tot].Next = head[u];
    head[u] = tot++;
}
//找出每一个节点往下的最大值和次大值 
void dfs1(int u, int fa)//求出以u为根节点的最大距离 
{
    
    maxlen[u] = smaxlen[u] = 0;
    for (int i = head[u]; i != -1; i = edge[i].Next)
    {
        int v = edge[i].to;
        if (v == fa)
            continue;
        dfs1(v, u);
        if (smaxlen[u] < maxlen[v] + edge[i].len)
        {
            smaxlen[u] = maxlen[v] + edge[i].len;
            smaxid[u] = v;
            if (maxlen[u] < smaxlen[u])
            {
                swap(maxlen[u], smaxlen[u]);
                swap(maxid[u], smaxid[u]);
            }
        }
    }
}
//找出从父节点过来和从当前点向下的最大值 
void dfs2(int u, int fa)
{
    for (int i = head[u]; i != -1; i = edge[i].Next)
    {
        int v = edge[i].to;
        if (v == fa)
            continue;
        if (v == maxid[u])//这里求的是v的而不是u的,和dfs1区分开,所以如果u取最大值时如果经过v的话,那么算从u过来的路径时要用次大值 
        {
            if (edge[i].len + smaxlen[u] > smaxlen[v])
            {
                smaxlen[v] = edge[i].len + smaxlen[u];
                smaxid[v] = u;
                if (maxlen[v] < smaxlen[v])
                {
                    swap(maxlen[v], smaxlen[v]);
                    swap(maxid[v], smaxid[v]);
                }
            }
        }
        else//否则用最大值 
        {
            if (edge[i].len + maxlen[u] > smaxlen[v])
            {
                smaxlen[v] = edge[i].len + maxlen[u];
                smaxid[v] = u;
                if (maxlen[v] < smaxlen[v])
                {
                    swap(maxlen[v], smaxlen[v]);
                    swap(maxid[v], smaxid[v]);
                }
            }
        }
        dfs2(v, u);
    }
}

int main()
{
    int n;
    while (~scanf("%d", &n))
    {
        init();
        int a, b;
        for (int i = 2; i <= n; i++)
        {
            scanf("%d %d", &a, &b);
            addedge(i, a, b);
            addedge(a, i, b);
        }
        dfs1(1, 0);
        dfs2(1, 0);
        for (int i = 1; i <= n; i++)
            printf("%d
", maxlen[i]);
    }    
    return 0;
}
原文地址:https://www.cnblogs.com/Howe-Young/p/4773890.html