题意:一个有N个结点的树,给你相邻两个结点的距离,问你对于第i个结点,树中离i最远的结点的距离是多少。
题解:可以通过两次树形DP求解。dp[i][3],i表示为在哪里结点,0表示子树中的最长距离,1表示子树中的次长距离,2表示父树的最长距离。
如果结点a本身就是父结点b最长子树距离上的结点,那么结点a最长父树结点就是结点b的次长子树距离或者结点b的最长父树距离。
代码:
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-9
#define maxn 10010
#define MOD 1000000007
const int MAXN = 10010;
struct Edge
{
int to,w,next;
} edge[MAXN<<1];
int tot,head[MAXN];
int n,m;
int dp[10010][3];
void add(int a,int b,int c)
{
edge[tot].to = b;
edge[tot].w = c;
edge[tot].next = head[a];
head[a] = tot++;
}
void dfs1(int x,int pre)
{
for(int i = head[x]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v == pre)
continue;
dfs1(v,x);
if(dp[v][0] + edge[i].w > dp[x][0])
{
dp[x][1] = dp[x][0];
dp[x][0] = dp[v][0] + edge[i].w;
}
else if(dp[v][0] + edge[i].w > dp[x][1])
dp[x][1] = dp[v][0] + edge[i].w;
}
}
void dfs2(int x,int pre)
{
int len = 0;
for(int i = head[x]; i != -1; i = edge[i].next)
{
if(edge[i].to == pre)
{
len = edge[i].w;
break;
}
}
if(pre != -1)
{
dp[x][2] = dp[pre][2];
if(dp[x][0] + len == dp[pre][0])
{
if(dp[pre][1] > dp[x][2])
dp[x][2] = dp[pre][1];
}
else if(dp[pre][0] > dp[x][2])
dp[x][2] = dp[pre][0];
dp[x][2] += len;
}
for(int i = head[x]; i != -1; i = edge[i].next)
if(edge[i].to != pre)
dfs2(edge[i].to,x);
}
int main()
{
int t,C = 1;
//scanf("%d",&t);
while(scanf("%d",&n) != EOF)
{
memset(dp,0,sizeof(dp));
memset(head,-1,sizeof(head));
tot = 0;
for(int i = 2; i <= n; i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(i,a,b);
add(a,i,b);
}
dfs1(1,-1);
dfs2(1,-1);
for(int i = 1; i <= n; i++)
printf("%d\n",max(dp[i][0],dp[i][2]));
}
return 0;
}