树上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);
}
}

京公网安备 11010502036488号