题意:有n台电脑,他们之间连着线,之间具有权值,问每一台电脑到哪台电脑的权值最大。
分析:这n台电脑的关系可以构成一棵树,问题即问到叶子结点的最远距离是多少。
设dp(i,0)表示以i为子树的最远叶子结点距离,dp(i,1)表示以i为子树的次远叶子结点距离,dp(i,2)表示tree(root)-tree(i)的最远距离+dis(root,i),root为i的父节点
要保存次远距离是因为,i的父节点的最远距离有可能会经过i,所以此时就要选择次远距离的值,而不能选择最远的。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10005;
struct node{
int v,w;
};
vector<node> com[maxn];
int dp[maxn][3]; //dp[i][0]表示以i为子树的最长距离,dp[i][1]表示以i为子树的次长距离,dp[i][2]表示i的根节点的最长距离加上i和根节点的距离
int visit[maxn];
void dfs1(int u){ //计算以i为子树的最长距离和次长距离
visit[u] = 1;
int max1 = 0,max2 = 0;
for(int i = 0;i < com[u].size();i++){
int V = com[u][i].v;
int W = com[u][i].w;
if(!visit[V]){
dfs1(V);
int tmp = dp[V][0] + W;
if(tmp >= max1){
max2 = max1;
max1 = tmp;
}
else if(tmp > max2){
max2 = tmp;
}
}
}
dp[u][0] = max1;
dp[u][1] = max2;
}
void dfs2(int u){
visit[u] = 1;
for(int i = 0;i < com[u].size();i++){
int V = com[u][i].v;
int W = com[u][i].w;
dp[V][2] = max(dp[u][2],dp[V][0] + W == dp[u][0] ? dp[u][1]:dp[u][0]) + W;
if(!visit[V])
dfs2(V);
}
}
int main(){
int n;
int a,b;
while(scanf("%d",&n) != EOF){
for(int i = 1;i <= n;i++)
com[i].clear();
for(int i = 2;i <= n;i++){
scanf("%d%d",&a,&b);
com[a].push_back(node{i,b});
}
memset(dp,0,sizeof(dp));
memset(visit,0,sizeof(visit));
dfs1(1);
memset(visit,0,sizeof(visit));
dfs2(1);
for(int i = 1;i <= n;i++){
printf("%d\n",max(dp[i][0],dp[i][2]));
}
}
return 0;
}