本旨:
概要:
各ポイントから最も遠い距離を見つけます
質問のアイデア:
典型的なテンプレートのアイデア
dp_uは、ポイントiから上にある最長のチェーンの長さを表します
dp_dは、ポイントiから下の最長のチェーンの長さを表します
マージするだけ
このブログは、将来のクエリの便宜のためだけのものであり、rootdpの置き換えについては注意深く説明していません。
コード:
/*** keep hungry and calm CoolGuang! ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define d(x) printf("%lld\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17;
const ll maxn = 2e5+700;
const int mod= 1e9+7;
const int up = 1e9;
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
vector<pair<int,int>>v[maxn];
ll dp_d[maxn][2],res[maxn],dp_u[maxn];
void dfs(int u,int fa){
for(auto x:v[u]){
int e = x.first,w = x.second;
if(e == fa) continue;
dfs(e,u);
if(dp_d[u][1] < dp_d[e][1]+w){
dp_d[u][0] = dp_d[u][1];
dp_d[u][1] = dp_d[e][1] + w;
}else if(dp_d[u][0] < dp_d[e][1] + w)
dp_d[u][0] = dp_d[e][1] + w;
}
}
void dfs(int u,int fa,int w){
ll res = 0;
if(u!=fa){
dp_u[u] = max(dp_u[u],w+dp_u[fa]);
if(dp_d[fa][1] == dp_d[u][1]+w) dp_u[u] = max(dp_u[u],w+dp_d[fa][0]);
else dp_u[u] = max(dp_u[u],w+dp_d[fa][1]);
}
for(auto x:v[u]){
int e = x.first;
if(e == fa) continue;
dfs(e,u,x.second);
}
}
int main(){
while(~scanf("%lld",&n)){
for(int i=1;i<=n;i++) v[i].clear();
for(int i=2;i<=n;i++){
int x,y;read(x);read(y);
v[x].push_back({i,y});
v[i].push_back({x,y});
}
for(int i=1;i<=n;i++) dp_d[i][0] = dp_d[i][1] = dp_u[i] = 0;
dfs(1,1);
dfs(1,1,1);
for(int i=1;i<=n;i++)
printf("%lld\n",max(dp_d[i][1],dp_u[i]));
}
return 0;
}
/***
4 3
0 0
1 0
2 0
3 1
****/