HDU 2196
题意:给一颗树,求出每个点到其距离最远的点的距离。
输入是,行的编号的点到第一个值的点的距离是第三个点的值;行的编号是从2开始的;
思路:每一个点距离其他点的最大距离只有可能来自两个方向,1是来自以改点为根的子树上,2是来自其父节点;但是有可能其父节点的第一种情况就是来自这个点(比如u->v,以u为根的子树上的最远距离来自以v节点为根的子树),所以在统计第一种情况是要统计最大值还有次大值,发生上述情况后用次大值就可达到最优解;
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct zp
{
int u,v,w,Next;
} node[10010];
int head[20010],cont;
int dp[10010][3];//0以该节点为根节点的最大值 1次大值 2来自父节点的最优解
void init()
{
memset(head,-1,sizeof(head));
memset(dp,0,sizeof(dp));
cont=0;
}
void dfs1(int u)//得出dp0和1的值
{
int maxn=0,smaxn=0;
for(int i=head[u];i!=-1;i=node[i].Next)
{
int v=node[i].v;
dfs1(v);
smaxn=max(smaxn,dp[v][0]+node[i].w);
if(smaxn>maxn)
swap(smaxn,maxn);
}
dp[u][0]=maxn;
dp[u][1]=smaxn;
}
void dfs2(int u)//得出dp2的值
{
for(int i=head[u];i!=-1;i=node[i].Next)
{
int v=node[i].v;
dp[v][2]=max(dp[u][2],dp[v][0]+node[i].w==dp[u][0]?dp[u][1]:dp[u][0])+node[i].w;//如果dp[v][0]+node[i].w==dp[u][0]则说明发生了上面提到的那种情况
dfs2(v);
}
}
void add_edge(int a,int b,int w)
{
node[cont].u=b,node[cont].v=a,node[cont].w=w;
node[cont].Next=head[b];
head[b]=cont++;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
init();
for(int i=2;i<=n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add_edge(i,a,b);
}
dfs1(1);
dp[1][2]=0;
dfs2(1);
for(int i=1;i<=n;i++)
printf("%d\n",max(dp[i][0],dp[i][2]));
}
}