分析:两遍dfs的树形dp裸题,记录子树最长链,然后自顶向下更新即可。。。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <stdlib.h> using namespace std; typedef long long LL; const int N=1e4+5; int T,n,head[N],tot,id[N]; LL ret[N],mx[N]; struct Edge{ int v,next; LL w; }edge[N<<1]; void add(int u,int v,LL w){ edge[tot].v=v; edge[tot].w=w; edge[tot].next=head[u]; head[u]=tot++; } void dfs(int u,int f){ mx[u]=0;id[u]=-1; for(int i=head[u];~i;i=edge[i].next){ int v=edge[i].v;if(v==f)continue;dfs(v,u); if(mx[v]+edge[i].w>mx[u]){mx[u]=mx[v]+1ll*edge[i].w;id[u]=v;} } } void get(int u,int f,LL x){ LL p=mx[u];ret[u]=max(mx[u],x); if(x>=p){p=x;id[u]=f;} for(int i=head[u];~i;i=edge[i].next){ int v=edge[i].v;if(v==f)continue; if(v!=id[u]){get(v,u,p+edge[i].w);continue;} LL tmp=x; for(int j=head[u];~j;j=edge[j].next){ int to=edge[j].v;if(to==f||to==v)continue; tmp=max(tmp,mx[to]+edge[j].w); } get(v,u,tmp+edge[i].w); } } int main(){ while(~scanf("%d",&n)){ for(int i=1;i<=n;++i)head[i]=-1; tot=0; for(int i=2;i<=n;++i){ int u,w;scanf("%d%d",&u,&w); add(u,i,w);add(i,u,w); } dfs(1,-1);get(1,-1,0); for(int i=1;i<=n;++i)printf("%I64d ",ret[i]); } return 0; }