hdu 2196 Computer(树形dp)

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

题意:在一个每条边都有权值的树中,求每个顶点能走的最大距离;

思路:两次dfs,以1为根结点,一次从叶子到根结点,求出最远距离和次远距离。另一次从根进行dfs.

(res[]为经过父节点能走最长距离)

代码:

View Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define sum 10010
using namespace std;
int f[sum] ={0};
int g[sum] ={0};
int biao[sum]= {0};
int res[sum] = {0};
int n = 0;
int a = 0;
int b = 0;
vector <int> son[sum],num[sum];
void init()
{
memset(f , 0, sizeof(f));
memset(g , 0, sizeof(g));
memset(biao , -1, sizeof(biao));
memset(res , 0, sizeof(res));
for(int i = 1;i <= n; ++i)
{
son[i].clear();
num[i].clear();
}
}
int dfs(int nn)
{
int nu = son[nn].size();
if( 0 == nu)
return 0;
for(int i = 0; i < nu ;++i)
{
int temp = dfs(son[nn][i]);
if(temp + num[nn][i] > g[nn])
{
if(temp + num[nn][i] >= f[nn])
{
g[nn] = f[nn];
f[nn] = temp + num[nn][i];
biao[nn] = i;
}
else
{
g[nn] = temp + num[nn][i];
}
}
}
return f[nn];
}
int max1(int a,int b)
{
if(a > b)
return a;
return b;
}
void dfs1(int nn)
{
int nu = son[nn].size();
for(int i = 0; i < nu ;++i)
{

if(i == biao[nn])
{
res[son[nn][i]] =max1(res[nn],g[nn]) + num[nn][i] ;
}

else
res[son[nn][i]] = max1(res[nn],f[nn]) + num[nn][i] ;
dfs1(son[nn][i]);
}
}
int main()
{
while(scanf("%d",&n) != EOF)
{
init();
for(int i = 2;i <= n; ++i)
{
scanf("%d%d",&a,&b);
son[a].push_back(i);
num[a].push_back(b);
}
f[1] = dfs(1);
dfs1(1);
res[1] = f[1];
for(int i = 1; i <= n; ++i)
printf("%d\n",max1(f[i],res[i]));
}
return 0;
}



posted @ 2012-02-21 21:56  LT-blogs  阅读(143)  评论(0编辑  收藏  举报