Computer
题目大意:
就是求树上每个点可到的最远距离,(不是树的直径)是单向可走的最远距离。
解题思路:
虽然不是树的直径但是也和树的直径有着一定的关系,在树形dp求树的直径中,f数组求的是该节点到子树的最远距离,这里我们也用到了这个东西。不过我们又新建了两个数组。
dp[i][0] 表示以 i 为根的子树上的节点到 i 的最长距离。 //之前的f数组
dp[i][1] 表示以 i 为根的子树上的节点到 i 的次长距离。
dp[i][2] 表示从 i 向父亲节点能走的最长距离。 //第二次dfs解得
(图画的好像有点乱 )
然后比较子树向下和父节点向上的路即可
Code:
#include <iostream>
#include <cstdio>
#include<cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#define inf 9654234
#define ll unsigned long long
using namespace std;
const int maxn=1e4+7;
const ll mod=4294967296;
int f[maxn],dp[maxn][3],mx[maxn],ans=0;
vector<pair<int,int>> ve[maxn];
void dfs(int u,int fa){
for(auto it:ve[u]){
int v=it.first;
int w=it.second;
if(v==fa) continue;
dfs(v,u);
if(dp[v][0]+w>dp[u][0]){
mx[u]=v;
dp[u][1]=dp[u][0];
dp[u][0]=dp[v][0]+w;
}
else if(dp[v][0]+w>dp[u][1]){
dp[u][1]=dp[v][0]+w;
}
}
}
void dfs2(int u,int fa){
for(auto it:ve[u]){
int v=it.first;
int w=it.second;
if(v==fa) continue;
if(v==mx[u]) dp[v][2]=w+max(dp[u][2],dp[u][1]);
else dp[v][2]=w+max(dp[u][2],dp[u][0]);
dfs2(v,u);
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int n;
while(cin>>n){
for(int i=1;i<=n;i++) {
ve[i].clear();
dp[i][0]=dp[i][1]=dp[i][2]=0;
}
for(int i=2;i<=n;i++){
int u,v,w;
cin>>v>>w;
ve[i].push_back(make_pair(v,w));
ve[v].push_back(make_pair(i,w));
}
dfs(1,0);
dfs2(1,0);
for(int i=1;i<=n;i++) cout<<max(dp[i][0],dp[i][2])<<"\n";
}
return 0;
}