现在的位置: 首页 > 综合 > 正文

HDU 2196 Computer (tree-DP 树的最长路 经典) #by Plato

2018年04月23日 ⁄ 综合 ⁄ 共 1485字 ⁄ 字号 评论关闭

http://acm.hdu.edu.cn/showproblem.php?pid=2196

引用下别人的:

题意:给定一棵树,求每一个节点所能到达的最长路径的长度

分析:以编号的i的节点为例(非根节点),最长的路径长度只有俩种可能,1)子树中存在最长路径;2)通过父节点的路径中存在最长路径

所以,只有分别求出每一节点对应的那俩种路径取大最大值即可,当然,根节点只存在第一种可能

上面也给出了思路,有个要注意的地方是:

通过父亲结点找的最长路径不能经过这个结点本身。

这就要求父节点保存两个最值(最大和次大)

Realize:

先建图,这里用邻接表存储较好。

 

DP

f[i]代表的是向下的最长路径

g[i]向下的次长路径

h[i]向上的最长路径

分两次DP

f[i]/g[i] = max{ f[child] } + w;

h[i] = max{h[parent], f[parent]/g[parent]} + w;

 

顺便学习了下STL里的vector的用法,有了STL,生活变得更简单~~~~

 

#include <cstdio>
#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
using namespace std;

#define MAX(a,b) ((a)>(b)?(a):(b))

struct edge
{
    int ev,w;
    edge(){}
    edge(int a,int b):ev(a),w(b){}
};
vector <edge> elist[10009];
int g[10009],f[10009],h[10009];

void DFS1(int fv)
{
    int size = elist[fv].size();
    if (!size)
    {
        f[fv] = g[fv] = 0;
        return;
    }

    int ev,w;
    for (int i = 0;i < size;i++)
    {
        ev = elist[fv][i].ev;
        w = elist[fv][i].w;
        DFS1(ev);
        if (f[ev] + w >= f[fv])
        {
            g[fv] = f[fv];
            f[fv] = f[ev] + w; //?
        }
        else
        {
            if (f[ev] + w > g[fv])
                g[fv] = f[ev] + w;
        }
    }
}

void DFS2(int fv)
{
    int size = elist[fv].size();
    if (!size)
    {
        return;
    }

    int ev,w;
    for (int i = 0;i < size;i++)
    {
        ev = elist[fv][i].ev;
        w = elist[fv][i].w;
        if (f[ev] + w != f[fv])
        {
            h[ev] = MAX(h[fv],f[fv]) + w;//h[i] = MAX(h[fv],f[fv]) + w;
        }
        else
        {
            h[ev] = MAX(h[fv],g[fv]) + w;
        }
        DFS2(ev);
    }
}

int main()
{
    freopen("test.txt","r",stdin);
    int N;
    while(~scanf("%d",&N))
    {
        for (int i = 1;i <= N;i++)
            elist[i].clear();
        int fv,w;
        for (int i = 2;i <= N;i++)
        {
            scanf("%d%d",&fv,&w);
            elist[fv].push_back(edge(i,w));
        }

        memset(f,0,sizeof(f));
        memset(g,0,sizeof(g));
        DFS1(1);
        DFS2(1);

        for (int i = 1;i <= N;i++)
        {
            //cout<<f[i]<<" "<<h[i]<<endl;
            printf("%d\n",MAX(f[i],h[i]));
        }
    }

    return 0;
}

抱歉!评论已关闭.