两次DFS,先从下往上搜一次,记录每个点到子树的最长距离与次长距离。次长距离的目的是如果在第二次更新的时候,最长距离与该子节点的方向是同一个方向,那就不能用这个最长距离了,只能用次长距离来更新。那么第二次dfs就是来从上往下来更新状态的。
代码如下:
#include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.h> using namespace std; #define LL __int64 #define pi acos(-1.0) const int mod=100000000; const int INF=0x3f3f3f3f; const double eqs=1e-8; int head[11000], cnt, dp[11000][3], id[11000][3]; struct node { int u, v, w, next; } edge[30000]; void add(int u, int v, int w) { edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } void dfs1(int u, int fa) { int i; for(i=head[u]; i+1; i=edge[i].next) { int v=edge[i].v; if(v==fa) continue ; dfs1(v,u); if(dp[u][1]<dp[v][0]+edge[i].w) { dp[u][1]=dp[v][0]+edge[i].w; id[u][1]=v; if(dp[u][1]>dp[u][0]) { swap(dp[u][0],dp[u][1]); swap(id[u][1],id[u][0]); } } } } void dfs2(int u, int fa) { int i, tmp; for(i=head[u]; i+1; i=edge[i].next) { int v=edge[i].v; if(v==fa) continue ; if(id[u][0]==v) tmp=dp[u][1]; else tmp=dp[u][0]; if(dp[v][1]<edge[i].w+tmp) { dp[v][1]=edge[i].w+tmp; id[v][1]=u; if(dp[v][1]>dp[v][0]) { swap(dp[v][1],dp[v][0]); swap(id[v][1],id[v][0]); } } dfs2(v,u); } } void init() { memset(head,-1,sizeof(head)); cnt=0; } int main() { int n, i, u, v, w; while(scanf("%d",&n)!=EOF) { init(); for(i=2; i<=n; i++) { scanf("%d%d",&v,&w); add(i,v,w); add(v,i,w); } memset(dp,0,sizeof(dp)); dfs1(1,0); dfs2(1,0); for(i=1; i<=n; i++) { printf("%d\n",dp[i][0]); } } return 0; }
原文地址:http://blog.csdn.net/scf0920/article/details/42834277