Give you a tree with values on both the vertex and edge. Define 2-path as the path that passes through an edge for a maximum of two times. The value is the weight value of the passing Vertex plus-passing Edge Weight * Number of times the edge passes. In the 4e5 group, the maximum value of 2-path connecting X and Y points on the query tree is displayed.
Question:
A tree-like DP with many statuses.
Dp1: record the value-X of the maximum 2-path from X to X in the X point tree.
Dp2: record the maximum value of 2-path-Fa [x] From Fa [x] to Fa [x] without X and without Fa [Fa [X.
Dp3: records the value of 2-path-X of any son from Fa [x] to Fa [x] without passing through X.
(The description is disgusting, as shown in the figure below)
(The picture is also disgusting)
An unknown object whose red edge and black are both required.
Then there is more common ds1: record the sum of vertices from X to the root, and DS2: record the sum of edges from X to the root.
It is also required that the sum of dp2.
Dfso (n) engages in DP and asks O (nlogn ).
Code that is more disgusting than descriptions and images:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 300050#define Q 400050#define ll long longint n,q,hed[N],cnt;struct EG{ int to,nxt; ll val;}e[2*N];void ae(int f,int t,ll v){ e[++cnt].to = t; e[cnt].val = v; e[cnt].nxt = hed[f]; hed[f] = cnt;}ll a[N];int dep[N],fa[N][25];ll ds1[N],ds2[N],E[N];void dfs1(int u,int f){ dep[u]=dep[f]+1; for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(to==f)continue; fa[to][0]=u; E[to]=e[j].val; ds1[to]=ds1[u]+a[to]; ds2[to]=ds2[u]+e[j].val; dfs1(to,u); }}int get_lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); for(int i=20;i>=0;i--) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i]; if(x==y)return x; for(int i=20;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0];}ll dp1[N],dp2[N];bool vis[N];void dfs(int u){ for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(to==fa[u][0])continue; dfs(to); if(dp1[to]+a[to]-2ll*e[j].val>=0) { dp1[u]+=dp1[to]+a[to]-2ll*e[j].val; vis[to]=1; } } for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(to==fa[u][0])continue; if(!vis[to])dp2[to]=dp1[u]; else dp2[to]=dp1[u]-(dp1[to]+a[to]-2ll*e[j].val); }}ll dp3[N],sum2[N];void Dfs(int u){ sum2[u]+=dp2[u]; for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(to==fa[u][0])continue; sum2[to]+=sum2[u]; dp3[to]=max(0ll,dp3[u]+1ll*a[u]+dp2[to]-2ll*e[j].val); Dfs(to); }}ll sol(int x,int y){ if(dep[x]>dep[y])swap(x,y); int lca = get_lca(x,y); if(x==lca) { return dp3[x]+dp1[y]+sum2[y]-sum2[x]+(ds1[x]+ds1[y]-ds1[lca]-ds1[fa[lca][0]])-(ds2[x]+ds2[y]-2ll*ds2[lca]); }else { int ffx = x,ffy = y; for(int i=20;i>=0;i--) { if(dep[fa[ffx][i]]>dep[lca]) ffx=fa[ffx][i]; if(dep[fa[ffy][i]]>dep[lca]) ffy=fa[ffy][i]; } return dp1[x]+dp1[y]+sum2[x]+sum2[y]-sum2[ffx]-sum2[ffy]+dp3[lca]+dp2[ffx]-(vis[ffy]==1)*(dp1[ffy]+a[ffy]-2ll*E[ffy])+(ds1[x]+ds1[y]-ds1[lca]-ds1[fa[lca][0]])-(ds2[x]+ds2[y]-2ll*ds2[lca]); }}int main(){ scanf("%d%d",&n,&q); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); ll v; for(int f,t,i=1;i<n;i++) { scanf("%d%d%lld",&f,&t,&v); ae(f,t,v),ae(t,f,v); } ds1[1]=a[1]; dfs1(1,1); for(int k=1;k<=20;k++) for(int i=1;i<=n;i++) fa[i][k]=fa[fa[i][k-1]][k-1]; dfs(1); Dfs(1); for(int x,y,i=1;i<=q;i++) { scanf("%d%d",&x,&y); printf("%lld\n",sol(x,y)); } return 0;}
Cf1000g two-paths