树形DP。求最长单链。用一种把自己也绕糊涂的方式做出来了- -!首先以第一台电脑为根节点,记录每个节点到每个子节点所属子孙节点中最长的距离。再求出除自己及自己子孙节点外到自己最长的距离。最后输出到自己子孙节点与到其他节点中最长的即可。
在求每个节点子节点最大值时,也要求出次大值,并记录最大值的下标,在求与其他节点最长距离时要用。
PS:在更新到子孙节点最大距离时,记得更新次大值。一开始在这里错了。调试时一开始以为是子节点数开小了。但是实际上开小了不是WA而是RE。而且刚开始还开大了,超内存,每个节点100个子节点足矣。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
struct Node
{
int par;
int son[105];//足矣
int num;
int mson[105];
int len;
int mx;
int mx_;
int mx2;
int ft;
}a[10005];
void init(int n)
{
for(int i=0;i<=n;i++)
{
a[i].par=i;
a[i].num=0;
a[i].len=0;
a[i].mx=0;
a[i].mx_=0;
a[i].mx2=0;
a[i].ft=0;
}
}
int v[10005];
int dfs(int x)
{
if(v[x]!=0)return a[x].mx;
for(int i=0;i<a[x].num;i++)
{
a[x].mson[i]=dfs(a[x].son[i])+a[a[x].son[i]].len;
if(a[x].mson[i]>a[x].mx)
{
if(a[x].mx!=0)
{
a[x].mx2=a[x].mx;
}
a[x].mx=a[x].mson[i];
a[x].mx_=a[x].son[i];
}
else if(a[x].mson[i]>a[x].mx2){a[x].mx2=a[x].mson[i];}
}
v[x]=1;
return a[x].mx;
}
int Ft(int x)
{
if(v[x])return a[x].ft;
v[x]=1;
int xx=Ft(a[x].par);
if(a[a[x].par].mx>xx)
{
if(a[a[x].par].mx_!=x)a[x].ft=a[a[x].par].mx;
else
{
if(a[a[x].par].mx2>xx){a[x].ft=a[a[x].par].mx2;}
else a[x].ft=xx;
}
}
else a[x].ft=xx;
a[x].ft+=a[x].len;
return a[x].ft;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(v,0,sizeof(v));
init(n);
int x,y;
for(int i=2;i<=n;i++)
{
scanf("%d%d",&x,&y);
a[i].par=x;
a[x].son[a[x].num]=i;
a[i].len=y;
a[x].num++;
}
dfs(1);
memset(v,0,sizeof(v));
v[1]=1;
for(int i=2;i<=n;i++)
{
Ft(i);
}
for(int i=1;i<=n;i++)
{
printf("%d\n",max(a[i].ft,a[i].mx));
}
}
return 0;
}