就是求每个点为起始点的最长链的长度。
写一下各个数组的意思吧。
f[i][0]为点i向下走最长的距离;f[i][1]为点i向下走第二长的距离;
xia[i][0]为点i向下走最长距离所要走的儿子节点;
xia[i][1]为点i向下走第二长长距离所要走的儿子节点;
f[i][2]为点i向上走的最大距离;
显而易见求向下的DP递推就好了。
求向上的DP
注意:两个DP都是从根节点往下更新。
#include<cstdio> #include<algorithm> #include<cstring> #define maxn 10010 << 1 using namespace std; int head[maxn],tot,n,u,v,val,len[maxn],f[maxn][3]; int xia[maxn][2],l[maxn]; struct st{ int v,val,next; st clear(){ v = val = next = 0; } }s[maxn]; void add(int u,int v,int val) { tot++; s[tot].v = v; s[tot].val = val; s[tot].next = head[u]; head[u] = tot; } void dfs(int fa,int now) { for(int i=head[now];i;i=s[i].next) if(s[i].v != fa) { l[s[i].v] = s[i].val; dfs(now,s[i].v); len[now] = max(len[s[i].v] + s[i].val,len[now]); int k = len[s[i].v] + s[i].val; if(f[now][1] < k) { f[now][1] = k; xia[now][1] = s[i].v; } if(f[now][1] > f[now][0]) { swap(xia[now][0],xia[now][1]); swap(f[now][1],f[now][0]); } } } void find(int fa,int now) { f[now][2] = max(f[fa][2] , now == xia[fa][0] ? f[fa][1] : f[fa][0]) + l[now]; for(int i=head[now];i;i=s[i].next) if(s[i].v != fa) find(now,s[i].v); } int main(){ while(scanf("%d",&n) != EOF) { for(int i=1;i<=2 * n;i++) { head[i] = f[i][0] = f[i][1] = f[i][2] = len[i] = l[i] = xia[i][0] = xia[i][1] = 0; s[i].clear(); } tot = 0; for(int i=2;i<=n;i++) { scanf("%d%d",&v,&val); add(i,v,val); add(v,i,val); } dfs(0,1); find(0,1); for(int i=1;i<=n;i++) printf("%d ",max(f[i][0],f[i][2])); } }