链接 : 传送门
题意: 给你一个n个节点的棵树,然后给你和 第i台电脑与第a台电脑相连的花费 v 问你最长的线路是多长(求树上任意节点所能达到的最远点的距离)
树形dp ,开个数组 分别记录这个点到子树最远节点的最长距离
和次长距离
和记录到父节点上的最长距离
这样在树上dp
1. 求子树最长
和 次长
dp[u][0] =max(dp[u][0],dfs(v,u)+val) 子树最长距离 =max(子树节点到子树的子树的最远距离 + 子树到根的距离 , 子树最长距离);
a. 最长更新
dp[u][1] =max(dp[u][1],dp[u][0])
b. 最长不更新
dp[u][1]=max(dp[u][1],dfs(v,u)+val)
2.求父节点
最长
a. 如果父节点最长子树通过
该节点,则父节点最长等于父节点次长加到子节点的距离
或者父节点在其父节点的最长加到子节点的距离
dp[v][2]=max(dp[u][2]+val,dp[u][1]+val)
b. 如果不通过那就是父节点最长等于父节点最长加到子节点的距离
或者父节点在其父节点的最长加到子节点的距离
dp[v][2]=max(dp[u][2]+val,dp[u][0]+val)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rd(a) scanf("%d",&a)
#define rlld(a) scanf("%lld",&a)
#define me(a,b) memset(a,b,sizeof(a))
const int inf= 0x3f3f3f3f;
const int maxn=1e4 + 3;
const ll mod =1e9+7;
int dist[maxn][3];
struct node{
int next,v,val;
}ss[maxn*2];
int head[maxn];
int pre[maxn];
int cnt=0;
inline void add(int u,int v,int val){
ss[cnt].v=v;
ss[cnt].val=val;
ss[cnt].next=head[u];
head[u]=cnt++;
}
inline void init (){
cnt=0;
me(head,-1);
me(dist,0);
me(pre,-1);
}
int dfs(int u,int fa)
{
for(int i=head[u];~i;i=ss[i].next){
int v=ss[i].v;
int val=ss[i].val;
if(v==fa) continue;
int ans=dfs(v,u);
if(ans+val>=dist[u][0]){
dist[u][1]=max(dist[u][0],dist[u][1]);
dist[u][0]=ans+val;
pre[u]=v;
}
else{
dist[u][1]=max(dist[u][1],ans+val);
}
}
return dist[u][0];
}
void dfs1(int u,int fa){
for(int i=head[u];~i;i=ss[i].next){
int v=ss[i].v;
int val=ss[i].val;
if(v==fa) continue;
if(pre[u]==v) dist[v][2]=max(dist[u][2]+val,dist[u][1]+val);
else dist[v][2]=max(dist[u][0]+val,dist[u][2]+val);
dfs1(v,u);
}
}
int main(){
int n;
while(cin>>n){
init();
for(int i=2;i<=n;i++)
{
int v,val;
cin>>v>>val;
add(v,i,val);
add(i,v,val);
}
dfs(1,-1);
dfs1(1,-1);
for(int i=1;i<=n;i++) cout<< max(dist[i][0],dist[i][2])<<endl;
}
return 0;
}