hdu 2196 Computer (树形DP)

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

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

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

View Code
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;
const int N = 10010;
int n,dist[N],dp[N];
struct edge
{
int v,w,h;
edge(){}
edge(int a,int b,int c=0):v(a),w(b),h(c){}
};
struct node
{
int w,id;
node(){}
node(int a,int b):w(a),id(b){}
};
vector<edge> g[N];
void init()
{
for(int i=0;i<=n;i++)
g[i].clear();
}
void dfs1(int u)
{
int size=g[u].size();
dist[u]=0;
node mdis1=node(0,0),mdis2=node(0,0);
//mdis1和mdis2 分别记录u的子树中的最长路径长度,以及所在的分支编号
for(int i=0;i<size;i++)
{
int v=g[u][i].v;
dfs1(v);
node t=node(g[u][i].w+dist[v],i);
if(t.w>mdis1.w)
{
mdis2=mdis1;
mdis1=t;
}
else if(t.w>mdis2.w)
mdis2=t;
}
dist[u]=mdis1.w;
for(int i=0;i<size;i++)
{
if(i==mdis1.id)
g[u][i].h=mdis2.w;//记录子树中,第i的儿子所在分支以外的最长路径
else g[u][i].h=mdis1.w;
}
}
void dfs2(int u)
{
int size=g[u].size();
for(int i=0;i<size;i++)
{
int v=g[u][i].v;
if(u==1)
{
dp[v]=g[u][i].h+g[u][i].w;
}
else {
dp[v]=max(dp[u],g[u][i].h)+g[u][i].w;//保存通过父亲节点的路径的最大长度
}
dfs2(v);
}
}
int main()
{
int x,w;
while(scanf("%d",&n)==1)
{
init();
for(int i=2;i<=n;i++)
{
scanf("%d %d",&x,&w);
g[x].push_back(edge(i,w,0));
}
dfs1(1);
memset(dp,0,sizeof(dp));
dp[1]=dist[1];
dfs2(1);
for(int i=1;i<=n;i++)
printf("%d\n",max(dp[i],dist[i]));
}
return 0;
}
原文地址:https://www.cnblogs.com/nanke/p/2382142.html