- 所有点权相等,等价于,任意一条边的两个端点点权差为0。容易发现一次操作只会改变一条树边的点权差。
- 不妨任取一点r为根节点,令\(a_r\)为初始答案,记\(d_u=a_u-a_{fau}\),显然\(d_u<0\)时的操作不影响答案,于是\(res=a_r+\sum_1^nmax(d_u,0)\),贪心地取子节点权值的最大值即可。
#include <bits/stdc++.h>
using namespace std;
vector<int>a[200005];
int f[200005],l[200005],r[200005];
long long ans;
void dfs(int n1,int fa)
{
int maxn=0;
for(int i=0;i<a[n1].size();i++)
{
if(a[n1][i]!=fa)
{
dfs(a[n1][i],n1);
maxn=max(maxn,f[a[n1][i]]);
}
}
if(maxn<l[n1])
{
f[n1]=l[n1];
}
else if(maxn>r[n1])
{
f[n1]=r[n1];
}
else
{
f[n1]=maxn;
}
for(int i=0;i<a[n1].size();i++)
{
if(a[n1][i]!=fa)
{
ans=ans+max(0,f[a[n1][i]]-f[n1]);
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>l[i]>>r[i];
a[i].clear();
}
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);
}
ans=0;
dfs(1,0);
cout<<ans+f[1]<<"\n";
}
return 0;
}