link
To change the root DP, it is recommended to use the following writing method, by storing the prefix extremum, so that there is no need for complicated classification discussions
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define per(i,a,b) for(ll i=(a);i>=(b);i--)
using namespace std;
typedef long long ll;
typedef vector<int> VI;
typedef pair<int,int> pii;
const ll inf = 1ll<<60;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 4;
const int N = 1000 + 5;
ll qpow(ll x,ll y){
ll ans=1;x%=mod;assert(y>=0);while(y){
if(y&1) ans=ans*x%mod; x=x*x%mod; y>>=1;}return ans;}
//ctrl + h 查询 替换 ctrl + shift + t 恢复刚刚关闭的标签
//ctrl + shift + d/k 复制/删除当前行
//alt + shift + 1/2/3/4 分屏
struct node {
ll x,y;};
int _,n;
VI G[maxn];
vector<node>kk[maxn];
ll a[maxn],b[maxn],dp[maxn][2],ans;
void dfs(int u,int fa) {
dp[u][0]=inf;dp[u][1]=-inf;
for(int v:G[u]) if(v!=fa) {
dfs(v,u);
dp[u][0]=min(dp[u][0],dp[v][1]);
dp[u][1]=max(dp[u][1],dp[v][0]);
}
if(dp[u][0]==inf) dp[u][1]=dp[u][0]=0;
dp[u][1]+=a[u];dp[u][0]+=a[u];
}
void dfs1(int u,int fa) {
dp[u][0]=inf;dp[u][1]=-inf;
for(int v:G[u]) {
dp[u][0]=min(dp[u][0],dp[v][1]);
dp[u][1]=max(dp[u][1],dp[v][0]);
kk[u].pb({
dp[u][0],dp[u][1]});
}
dp[u][0]+=a[u];dp[u][1]+=a[u];
ans=max(ans,dp[u][0]);
ll t0=inf,t1=-inf;
for(int i=SZ(G[u])-1;i>=0;i--) {
dp[u][0]=t0;dp[u][1]=t1;
if(i) {
dp[u][0]=min(kk[u][i-1].x,dp[u][0]);
dp[u][1]=max(kk[u][i-1].y,dp[u][1]);
}
if(dp[u][0]==inf) dp[u][0]=dp[u][1]=0;
dp[u][0]+=a[u];dp[u][1]+=a[u];
int v=G[u][i];
t0=min(t0,dp[v][1]);
t1=max(t1,dp[v][0]);
if(v!=fa) dfs1(v,u);
}
}
int main() {
//freopen("input.in","r",stdin);
for(scanf("%d",&_);_;_--) {
scanf("%d",&n);rep(i,1,n) G[i].clear(),kk[i].clear();
rep(i,1,n) scanf("%lld",&a[i]);
rep(i,1,n) scanf("%lld",&b[i]),a[i]-=b[i];
rep(i,2,n) {
int u,v;scanf("%d%d",&u,&v);
G[u].pb(v);G[v].pb(u);
}
dfs(1,-1);ans=dp[1][0];
dfs1(1,-1);
printf("%lld\n",ans);
}
return 0;
}