用了两种做法, 一种是每一个节点做根来扫
果断O(n(n+m)) 显然不行
另一种是1做根,判断每种情况
把另外一个孩子节点的最大值和连上去的值加起来做treedp即可
时间复杂度O(n+m)
Code:
#include<cstdio>
#include<iostream>
#include<cstring>
#define max(x,y) (x)>(y)?(x):(y)
using namespace std;
int n;
struct node
{
int x,y,d,next,sum;
}a[110000]; int len,first[110000];
void ins(int x,int y,int d)
{
len++; a[len].x=x; a[len].y=y; a[len].d=d;
a[len].next=first[x]; first[x]=len;
}
void Input()
{
int y,d;
len=0; memset(first,0,sizeof(first));
for(int i=2;i<=n;i++)
{
scanf("%d%d",&y,&d);
ins(i,y,d); ins(y,i,d);
}
}
__int64 dp[110000]; bool vis[110000];
void Treedp(int x)
{
if(vis[x]) return ;
vis[x]=1;
for(int k=first[x];k;k=a[k].next)
{
int y=a[k].y;
if(!vis[y])
{
Treedp(y);
dp[x]=max(dp[x],dp[y]+a[k].d);
a[k].sum=dp[y]+a[k].d;
}
}
}
void Treedp2(int fa,int x)
{
if(vis[x]) return ;
vis[x]=1;
int maxx=0;
for(int k=first[fa];k;k=a[k].next)
{
int y=a[k].y;
if(y!=x)
maxx=max(maxx,a[k].sum);
}
for(int k=first[x];k;k=a[k].next)
{
int y=a[k].y;
if(y==fa)
{
a[k].sum=a[k].d+maxx;
break;
}
}
for(int k=first[x];k;k=a[k].next)
{
int y=a[k].y;
dp[x]=max(dp[x],a[k].sum);
Treedp2(x,y);
}
}
void Solve()
{
int root=1;
memset(vis,0,sizeof(vis));
memset(dp,0,sizeof(dp));
Treedp(root);
memset(vis,0,sizeof(vis));
for(int k=first[root];k;k=a[k].next)
{
Treedp2(root,a[k].y);
}
}
void Output()
{
for(int i=1;i<=n;i++)
printf("%I64d\n",dp[i]);
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
while(scanf("%d",&n)!=EOF)
{
Input();
Solve();
Output();
}
return 0;
}