Parsa‘s Humongous Tree(贪心+树形dp)

23 篇文章 0 订阅
8 篇文章 0 订阅

今天来给大家分享一道考察贪心的题目:

Parsa has a humongous tree on nn vertices.

On each vertex v he has written two integers lv and rv.

To make Parsa's tree look even more majestic, Nima wants to assign a number avav (lv≤av≤rv) to each vertex v such that the beauty of Parsa's tree is maximized.

Nima's sense of the beauty is rather bizarre. He defines the beauty of the tree as the sum of |au−av| over all edges (u,v) of the tree.

Since Parsa's tree is too large, Nima can't maximize its beauty on his own. Your task is to find the maximum possible beauty for Parsa's tree.

Input

The first line contains an integer t(1≤t≤250) — the number of test cases. The description of the test cases follows.

The first line of each test case contains a single integer n(2≤n≤105) — the number of vertices in Parsa's tree.

The i-th of the following n lines contains two integers lili and ri (1≤li≤ri≤109).

Each of the next n−1n−1 lines contains two integers uu and vv (1≤u,v≤n,u≠v)(1≤u,v≤n,u≠v) meaning that there is an edge between the vertices u and v in Parsa's tree.

It is guaranteed that the given graph is a tree.

It is guaranteed that the sum of nn over all test cases doesn't exceed 2⋅10^5.

Output

For each test case print the maximum possible beauty for Parsa's tree.

Example

Input

3
2
1 6
3 8
1 2
3
1 3
4 6
7 9
1 2
2 3
6
3 14
12 20
12 19
2 12
10 17
3 17
3 2
6 5
1 5
2 6
4 6

Output

7
8
62

先翻译一下题意:

从前有一棵 n 个点的大树,每个顶点 v 上有两个数lv,rv

为了使这棵树看起来更加雄伟,小羊驼 想为每个顶点 v 分配一个数字 av (lv≤av≤rv),从而最大化 这棵树的价值。

小羊驼将树的价值定义为:对于在树的所有边 (u,v) 其 |au−av| 的总和。 由于这棵树太大了,小羊驼算不出他的最大价值是多少,你的任务是帮助小羊驼算出这棵树的最大价值。

这道题目是道贪心题,我们每次选每个点的边界值就能够得到最优答案,现在来对这种贪心思路做出证明:

我们假设一个点x的所有子节点的数字都已经确定,我们先在x可选的区间内随意选择一个值y,假如他的子结点中的数字大于y的有p个,小于y的有q个,则对于x的边的最大价值∑| ax−aj | (j为x的子节点) 则会增加q,减少p,如果p>q,为了使最大价值增加,我们应该使y尽可能小,达到左边界时取得最大值,反之如果p<q,那我们应该使y尽可能增大,使得y到达右边界,这样我们就证明了最优答案一定是取在边界值上得到的。剩下的就是一个树形dp了,下面是代码:

   

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
typedef long long ll;
const int N=50000;
int h[N],e[N],w[N],ne[N],idx;
ll dp[N][2];
//dp[i][0]表示第i个点选左边界时,以i为根的子树所取得的最大价值 
//dp[i][1]表示第i个点选右边界时,以i为根的子树所取得的最大价值
int l[N],r[N];
int n;
void add(int x,int y)
{
	e[idx]=y;
	ne[idx]=h[x];
	h[x]=idx++;
}
void dfs(int x,int father)
{
	for(int i=h[x];i!=-1;i=ne[i])
	{
		int j=e[i];
		if(j==father) continue;
		dfs(j,x);
		dp[x][0]+=max(abs(l[x]-l[j])+dp[j][0],abs(l[x]-r[j])+dp[j][1]);
		dp[x][1]+=max(abs(r[x]-l[j])+dp[j][0],abs(r[x]-r[j])+dp[j][1]);
	}
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		memset(h,-1,sizeof h);
		memset(dp,0,sizeof dp);
		idx=0;
		scanf("%d",&n);
		int u,v;
		for(int i=1;i<=n;i++)
			scanf("%d%d",&l[i],&r[i]);
		for(int i=1;i<n;i++)
		{
			scanf("%d%d",&u,&v);
			add(u,v);add(v,u);
		}
		dfs(1,0);
		printf("%lld\n",max(dp[1][0],dp[1][1]));
	}
	return 0;
}

这就是这道题目的分析了,贪心是一个比较难的问题,关键是思路不好想,如果大佬有好的贪心题目的话,欢迎分享!

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值