題目鏈接:點對最大值
顯然可以樹dp。
dp[x]爲從子樹到點x的最大權值。
然後我們每次對一個點記錄,從子樹來的最大值和次大值。
每次轉移即可,或者是直接到根。
要注意初始值爲-1e9而不是0
AC代碼:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6+10,M=N<<1;
int dp[N],res,c[N],n;
int head[N],to[M],w[M],nex[M],tot;
inline void add(int a,int b,int c){to[++tot]=b; nex[tot]=head[a]; w[tot]=c; head[a]=tot;}
void dfs(int x,int fa){
dp[x]=-1e9; int mx1=-1e9,mx2=-1e9;
for(int i=head[x];i;i=nex[i]) if(to[i]!=fa){
dfs(to[i],x); int tmp=w[i]+dp[to[i]];
dp[x]=max(dp[x],tmp);
if(tmp>mx1) mx2=mx1,mx1=tmp;
else if(tmp>mx2) mx2=tmp;
}
res=max(res,dp[x]+c[x]);
res=max(res,mx1+mx2);
dp[x]=max(dp[x],c[x]);
}
inline void solve(){
cin>>n; tot=0; memset(head,0,sizeof head); res=-1e9;
for(int i=2,a,b;i<=n;i++) scanf("%d %d",&a,&b),add(i,a,b),add(a,i,b);
for(int i=1;i<=n;i++) scanf("%d",&c[i]);
dfs(1,0); cout<<res<<endl;
}
signed main(){
int T; cin>>T; while(T--) solve();
return 0;
}