#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
#include<cmath>
#include<iomanip>
#include<map>
#include<stdio.h>
#pragma optimize(2)
#define INF 0x3f3f3f3f
#define ll long long
#define pll pair<ll,ll>
#define pdl pair<double,ll>
#define pdd pair<double, double>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) 
using namespace std;
const ll N = 2e5 + 5;
/*
每一个点的beauty值大小，只与与其相邻的点的数量有关，能使其与其周围点beauty值达到最大的值a一定是当前点的l,r二者其一
因为：
设p为与当前点相邻且a大于当前点a的点的数量，q为与当前点相邻且a小于当前点a的点的数量
若p>q，那么可以令当前点的a等于l达到最优解，若p<q,可以令当前点的a等于r达到最优解，若p=q，那么a取任何值不会影响答案
令dp[v][0]表示当前点取l，dp[v][1]表示当前点取r
则对与v相邻的每一个孩子u：
dp[v][0]+=max{dp[u][0]+abs(v[l]-u[l]),dp[u][1]+abs(v[l]-u[r])};
dp[v][1]+=max{dp[u][0]+abs(v[r]-u[l]),dp[u][1]+abs(v[r]-u[r])};
*/
ll n;
struct node {
	ll l, r;
	ll dp[2] = { 0 };
}p[N];
ll h[N], e[N], ne[N], idx;
void add(ll a,ll b)
{
	e[idx] = b;
	ne[idx] = h[a];
	h[a] = idx++;
}
ll dfs(ll cur,ll pre,ll f)
{
	if (p[cur].dp[f] != 0)return p[cur].dp[f];

	for (ll i = h[cur]; i != -1; i = ne[i])
	{
		ll j = e[i];
		if (j == pre)continue;
		if (f == 0) {
			p[cur].dp[0] += max(dfs(j,cur, 0) + abs(p[cur].l - p[j].l), dfs(j,cur, 1) + abs(p[cur].l - p[j].r));
		}
		else
		{
			p[cur].dp[1] += max(dfs(j,cur, 0) + abs(p[cur].r - p[j].l), dfs(j,cur, 1) + abs(p[cur].r - p[j].r));
		}
	}
	//cout << "p[" << cur << "].dp[" << f << "]==" << p[cur].dp[f] << endl;
	return p[cur].dp[f];
}
void solve()
{
	cin >> n;
	memset(h, -1, sizeof h);
	idx = 0;
	for (ll i = 1; i <= n; i++)
	{
		cin >> p[i].l >> p[i].r;
		p[i].dp[0] = 0;
		p[i].dp[1] = 0;
	}
	for (ll i = 1; i <= n - 1; i++)
	{
		ll u, v;
		cin >> u >> v;
		add(u, v);
		add(v, u);
	}
	ll ans = max(dfs(1, -1,0), dfs(1, -1,1));
	cout << ans << endl;
}
int main()
{
	IOS;
	ll t;
	cin >> t;
	while (t--)
	{
		solve();
	}
}