andre_joy

导航

hdu 2196

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

题意:有很多机器通过一棵树连在一起,每条边有一个权值,求每个机器距离最远的路径是多长。

mark:这是一个典型的起点不固定的树形dp。我们首先想到的肯定是枚举所有顶点,但是这样计算会有很多重复计算,我们做dp就是为了减少重复计算。

    于是我们可以先把它当成一个以任意节点(一般都以编号为1的节点)当根节点做一次dp,dp[i]代表以i为根的子树的最大权值。做完一次后根节点(节点1)肯定已经是最优的了,那么我们现在要想办法更新其他的节点,假如现在要更新节点1的儿子节点son,那么我们首先要计算出除了1到son以外的别的1出发到儿子节点的权值的最大,然后更新一下son目前的值,代码中有注释。然后再从son节点继续往下更新,这样就不减少了很多重复计算,最后每个节点都是最优的情况。

    废话不多说,看代码吧~

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h> 

const int N = 10010;

struct node {

    int v,w,sum;
    node *next;
}*head[N],tree[2*N];
int n,m,ptr;
int vst[N],dp[N];

int max(int a, int b) {return a > b ? a : b;}

void init()
{
    ptr = 1;
    memset(vst, 0, sizeof(vst));
    memset(dp, 0, sizeof(dp));
    memset(head, 0, sizeof(head));
}

void AddEdge(int x,int y, int z)
{
    tree[ptr].v = y;
    tree[ptr].w = z;
    tree[ptr].next = head[x],head[x] = &tree[ptr++];
}

void dfs(int v)   //v代表父亲节点  
{
    vst[v] = 1;
    node *p = head[v];
    while (p != NULL)
    {
        if(vst[p->v]) {p = p->next; continue;}
        dfs(p->v);    //p->v代表v的儿子节点 
        dp[v] = max(dp[v], dp[p->v]+p->w);
        p->sum = dp[p->v]+p->w;
        p = p->next;
    }
}

void tree_dp(int fa, int son)
{
    if(vst[son]) return ;
    vst[son] = 1;
    int i,j,k,max1;
    node *p = head[fa];
    max1 = 0;
    while(p != NULL)  //找到除了儿子节点以外的节点权值最大 
    {
        if(p->v != son) max1 = max(max1, p->sum);
        p = p->next;
    }
    p = head[son];
    while(p != NULL)  //更新一下儿子节点(假定当根节点)的权值 
    {
        if(p->v == fa)
        {
            p->sum = p->w+max1;
            break;
        }
        p = p->next;
    }
    p = head[son];
    while(p != NULL)  //更新儿子节点的最终权值,同时把继续搜寻儿子的儿子节点…… 
    {
        dp[son] = max(dp[son], p->sum);
        tree_dp(son, p->v);
        p = p->next;
    }
} 


int main()
{
    int i,j,k;
    while(~scanf("%d", &n))
    {
        init();
        for(i = 2; i <= n; i++)
        {
            scanf("%d%d", &j, &k);
            AddEdge(i, j, k);
            AddEdge(j, i, k);
        }
        dfs(1);
        memset(vst, 0, sizeof(vst));
        node *p = head[1];
        while(p != NULL)
        {
            tree_dp(1, p->v);
            p = p->next;
        }
        for(i = 1; i <= n; i++)
            printf("%d\n", dp[i]);
    }
}

posted on 2012-10-11 09:59  andre_joy  阅读(785)  评论(0编辑  收藏  举报