考虑树形dp,好像以前做过类似的cf题,贪心一下,选取两边的边界能使得答案最大,所以设f[i][j]为第i个结点取左边界还是右边界,转移的时候枚举两个边界就可以了
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<list>
#include<cmath>
#define int long long
using namespace std;
int t,n,l[100005],r[100005],f[100005][2];//0 l,1 r;
bool vis[100005];
list<int>lis[100005];
void dfs(int rt)
{
vis[rt]=true;
for(list<int>::iterator it=lis[rt].begin();it!=lis[rt].end();it++)
{
if(!vis[*it])
{
dfs(*it);
f[rt][0]+=max(f[*it][0]+abs(l[rt]-l[*it]),f[*it][1]+abs(l[rt]-r[*it]));
f[rt][1]+=max(f[*it][0]+abs(r[rt]-l[*it]),f[*it][1]+abs(r[rt]-r[*it]));
}
}
}
signed main()
{
cin>>t;
while(t--)
{
memset(f,0,sizeof(f));
memset(vis,false,sizeof(vis));
scanf("%lld",&n);
for(int i=1;i<=n+2;i++)
{
lis[i].clear();
}
for(int i=1;i<=n-1;i++)
{
int u,v;
scanf("%lld %lld",&u,&v);
lis[u].push_back(v);
lis[v].push_back(u);
}
//lis[n].clear();
for(int i=1;i<=n;i++)
{
//lis[i].clear();
scanf("%lld %lld",&l[i],&r[i]);
}
dfs(1);
//int ans=0;
/*for(int i=1;i<=n;i++)
{
ans+=f[i];
}*/
printf("%lld\n",max(f[1][0],f[1][1]));
}
}