Computer
题意:n台电脑由n-1根网线连接,构成一棵树;问每个电脑和最远连接的电脑之间的距离最大是多少;
思路:如果是求某一个点到达的最远的电脑,直接深搜一遍就可以了,但是本题是要求出所有的点的最长到达点,总不能每个点都跑一边dfs吧;
首先明确一点一个节点的最长到达距离是什么?要么是一本节点向下到叶子节点的距离,要么是向上到父节点,再由父节点向下到叶子节点(经由该节点的兄弟节点)的距离或者是到父节点的父节点到叶子节点;
有点递归的意思;
那么可以分为两类:
1:向下的距离down[i]; 2:向上的距离up[i];
向下的距离更新就是在儿子节点中选一个到叶子距离最长的点连接
down[i]=max{down[son]+dis[son] | son是i的子节点};
向上的距离是有父节点过来的,要么是父节点向上的距离,要么是父节点经由i的兄弟节点向下的距离;
up[i]=max(up[father], down[father]);
#include <bits/stdc++.h>
using namespace std;
const int maxn=10010;
long long down[maxn][2], up[maxn];
struct node{
int v, dis, nxt;
node(){}
node(int v0, int d, int n){
v=v0, dis=d, nxt=n;
}
}edge[maxn<<1];
int head[maxn], cnt;
void add(int u, int v, int dis){
edge[cnt]=node(v, dis, head[u]);
head[u]=cnt++;
}
int path[maxn];
void dfs0(int u, int fa){
long long mx1=0, mx0=0;
for(int i=head[u]; i!=-1; i=edge[i].nxt){
int v=edge[i].v, dis=edge[i].dis;
if(v==fa) continue;
dfs0(v, u);
if(mx0<=down[v][0]+dis){
mx1=mx0;
mx0=down[v][0]+dis;
path[u]=v;
}
else if(mx1<down[v][0]+dis) mx1=down[v][0]+dis;
}
down[u][0]=mx0;
down[u][1]=mx1;
}
void dfs1(int u, int fa){
for(int i=head[u]; i!=-1; i=edge[i].nxt){
int v=edge[i].v, dis=edge[i].dis;
if(v==fa) continue;
if(path[u]==v) up[v]=max(down[u][1]+dis, up[u]+dis);
else up[v]=max(down[u][0]+dis, up[u]+dis);
dfs1(v, u);
}
}
int main(){
int N;
while(~scanf("%d", &N)){
int a, b;
memset(down, 0, sizeof(down));
memset(up, 0, sizeof(up));
memset(head, -1, sizeof(head));
cnt=0;
for(int i=2; i<=N; i++){
scanf("%d%d", &a, &b);
add(i, a, b);
add(a, i, b);
}
dfs0(1, 1);
dfs1(1, 1);
for(int i=1; i<=N; i++){
printf("%lld\n", max(down[i][0], up[i]));
}
}
return 0;
}