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