D. Balanced Tree

  • 所有点权相等,等价于,任意一条边的两个端点点权差为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;
}
posted @ 2025-01-29 15:20  D06  阅读(17)  评论(0)    收藏  举报
//雪花飘落效果