题意:一个有N个结点的树,给你相邻两个结点的距离,问你对于第i个结点,树中离i最远的结点的距离是多少。
思路:每一个节点有两种情况,一种是在子树中,一种是在非子树中,所以就可以用两次的dfs分别求出两种最长距离
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <string.h>
using namespace std;
const int N=10005;
struct edge{
int u,v,w,next;
void init(int x,int y,int z,int nn){
u=x,v=y,w=z,next=nn;
}
}e[N<<1];
int k,n;
int first[N],dp[N][2],dq[N]; //dp[i][0]i节点的子树中最长距离,dp[i][1]次长 dq[i]i节点向父节点方向的最长距离
void addedge(int u,int v,int w){
e[k].init(u,v,w,first[u]);
first[u]=k++;
e[k].init(v,u,w,first[v]);
first[v]=k++;
}
void init(){
k=0;
memset(first,-1,sizeof(first));
memset(dp,0,sizeof(dp));
memset(dp,0,sizeof(dq));
}
//第一个dfs是求dp的
void dfs1(int u,int fa){
//printf("dfs1(%d,%d)\n",u,fa);
for(int i=first[u];~i;i=e[i].next){
int v=e[i].v;
if(v==fa)continue;
dfs1(v,u);
if(dp[u][0]<=dp[v][0]+e[i].w){
dp[u][1]=dp[u][0];
dp[u][0]=dp[v][0]+e[i].w;
}
else if(dp[u][1]<dp[v][0]+e[i].w){
dp[u][1]=dp[v][0]+e[i].w;
}
}
}
//第二个是求dq的
void dfs2(int u,int fa){
//printf("dfs2(%d,%d)\n",u,fa);
int len=0;
for(int i=first[u];~i;i=e[i].next){
if(e[i].v==fa){
len=e[i].w;
break;
}
}
if(fa!=-1){
if(dp[u][0]+len==dp[fa][0]){ //如果u是fa的子树最长路径上的点
dq[u]=max(dq[fa],dp[fa][1])+len; //那么dq[u]=max(fa的非子树最长距离,fa子树次长距离)+len;
}
else {
dq[u]=max(dq[fa],dp[fa][0])+len; //否则dq[u]=max(fa的非子树最长距离,fa子树最长长距离)+len;
}
}
for(int i=first[u];~i;i=e[i].next){
if(e[i].v==fa){continue;}
dfs2(e[i].v,u);
}
}
int main(){
int x,y;
while(~scanf("%d",&n)){
init();
for(int i=2;i<=n;i++){
scanf("%d%d",&x,&y);
addedge(i,x,y);
}
dfs1(1,-1);
dfs2(1,-1);
for(int i=1;i<=n;i++)printf("%d\n",max(dq[i],dp[i][0]));
}
}