树上dp。
记low1[u]为从u向下搜索到的最大路径值加起点值,low2[u]为从u向下搜索到的次大路径值加起点值。
考虑非叶子节点u及以其为根的子树:
若u为端点,则ans=max(ans,low1[u]+weight[u]);
若u不为端点,则ans=max(ans,low1[u]+low2[u])。

对于dfs遍历到的每个非叶子节点都以此更新ans的值;
对于叶子节点则令low1[u]=weight[u],low2[u]=-inf,因为同一段路径不能经过两次。

代码:

#include <iostream>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cctype>
#include <functional>
#include <string>
#include <cstring>
#include <sstream>
#include <deque>
using namespace std;

typedef long long ll;
typedef pair<int,int> P;
typedef pair<P,int> Q;

const int inf1=1e9+9;
const ll inf2=8e18+9;
const ll mol=998244353;
const int maxn=1e6+9;
const int maxx=1e9+9;

int n;
int weight[maxn];
struct st{int to,w,next;} ar[maxn+maxn];
int head[maxn+maxn],cnt;
int low1[maxn],low2[maxn];
int ans;

inline void add(int u,int v,int w)
{
    ar[++cnt].to=v;
    ar[cnt].w=w;
    ar[cnt].next=head[u];
    head[u]=cnt;
}
inline void swap_3(int &mi,int &ma,int t)
{
    if(t>=ma) mi=ma,ma=t;
    if(mi<t&&t<ma) mi=t;
}
void dfs(int u,int pre)
{
    low1[u]=low2[u]=-inf1;
    for(int i=head[u];i!=-1;i=ar[i].next)
    {
        int v=ar[i].to;
        if(v==pre) continue;
        dfs(v,u);
        swap_3(low2[u],low1[u],low1[v]+ar[i].w);
    }
    ans=max(ans,low1[u]+weight[u]);
    ans=max(ans,low1[u]+low2[u]);
    low1[u]=max(low1[u],weight[u]);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        cnt=0; ans=-inf1;
        memset(head,-1,sizeof head);
        scanf("%d",&n);
        for(int i=2;i<=n;i++)
        {
            int v,w;
            scanf("%d%d",&v,&w);
            add(i,v,w);
            add(v,i,w);
        }
        for(int i=1;i<=n;i++) scanf("%d",&weight[i]);
        dfs(1,-1);
        printf("%d\n",ans);
    }
}