Jeremy Bearimy(树形dp)

Welcome! Everything is fine.

You have arrived in The Medium Place, the place between The Good Place and The Bad Place. You are assigned a task that will either make people happier or torture them for eternity.

You have a list of kk pairs of people who have arrived in a new inhabited neighborhood. You need to assign each of the 2k2k people into one of the 2k2k houses. Each person will be the resident of exactly one house, and each house will have exactly one resident.

Of course, in the neighborhood, it is possible to visit friends. There are 2k−12k−1 roads, each of which connects two houses. It takes some time to traverse a road. We will specify the amount of time it takes in the input. The neighborhood is designed in such a way that from anyone’s house, there is exactly one sequence of distinct roads you can take to any other house. In other words, the graph with the houses as vertices and the roads as edges is a tree.

The truth is, these kk pairs of people are actually soulmates. We index them from 11 to kk. We denote by f(i)f(i) the amount of time it takes for the ii-th pair of soulmates to go to each other’s houses.

As we have said before, you will need to assign each of the 2k2k people into one of the 2k2k houses. You have two missions, one from the entities in The Good Place and one from the entities of The Bad Place. Here they are:

The first mission, from The Good Place, is to assign the people into the houses such that the sum of f(i)f(i) over all pairs ii is minimized. Let’s define this minimized sum as GG. This makes sure that soulmates can easily and efficiently visit each other;
The second mission, from The Bad Place, is to assign the people into the houses such that the sum of f(i)f(i) over all pairs ii is maximized. Let’s define this maximized sum as BB. This makes sure that soulmates will have a difficult time to visit each other.
What are the values of GG and BB?

Input
The first line of input contains a single integer tt (1≤t≤5001≤t≤500) denoting the number of test cases. The next lines contain descriptions of the test cases.

The first line of each test case contains a single integer kk denoting the number of pairs of people (1≤k≤1051≤k≤105). The next 2k−12k−1 lines describe the roads; the ii-th of them contains three space-separated integers ai,bi,tiai,bi,ti which means that the ii-th road connects the aiai-th and bibi-th houses with a road that takes titi units of time to traverse (1≤ai,bi≤2k1≤ai,bi≤2k, ai≠biai≠bi, 1≤ti≤1061≤ti≤106). It is guaranteed that the given roads define a tree structure.

It is guaranteed that the sum of the kk in a single file is at most 3⋅1053⋅105.

Output
For each test case, output a single line containing two space-separated integers GG and BB.

Example
Input
2
3
1 2 3
3 2 4
2 4 3
4 5 6
5 6 5
2
1 2 1
1 3 2
1 4 3
Output
15 33
6 6
Note
For the sample test case, we have a minimum sum equal to G=15G=15. One way this can be achieved is with the following assignment:

The first pair of people get assigned to houses 55 and 66, giving us f(1)=5f(1)=5;
The second pair of people get assigned to houses 11 and 44, giving us f(2)=6f(2)=6;
The third pair of people get assigned to houses 33 and 22, giving us f(3)=4f(3)=4.
Note that the sum of the f(i)f(i) is 5+6+4=155+6+4=15.

We also have a maximum sum equal to B=33B=33. One way this can be achieved is with the following assignment:

The first pair of people get assigned to houses 11 and 44, giving us f(1)=6f(1)=6;
The second pair of people get assigned to houses 66 and 22, giving us f(2)=14f(2)=14;
The third pair of people get assigned to houses 33 and 55, giving us f(3)=13f(3)=13.
Note that the sum of the f(i)f(i) is 6+14+13=336+14+13=33.
题意:给定k对点,一共2*k个点。构成一棵树。每两个点之间的距离为ti。现在给k对人安排地方,求出所有对人安排地方的距离和最大值与最小值。
思路:这种树形dp的题目,很多都是从边的角度出发去寻找。
①对于求最大值来说,我们希望每一条边都尽可能的多被利用。对于每一条边,我们应该求出这条边连接的子树size以及另一边的size之间的最小值,然后乘以这条边的权值,这样加起来就是最大值了。
②对于求最小值来说,每一条边能不用就不用,这就是贪心的策略了。如果这条边连接的一端有偶数个点的话,那么另一端也有偶数个点,这样就可以两两组成一对,这一条边就可以不用了。相反,如果两端都有奇数个点的话,这一条边就必须得用。
两个问题,一遍dfs就可以了。
代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxx=6e5+100;
struct edge{
	int next;
	int to;
	int val;
}e[maxx<<1];
int head[maxx];
int k,n,tot=0;

inline void add(int u,int v,int c)
{
	e[tot].to=v,e[tot].val=c,e[tot].next=head[u],head[u]=tot++;
}
inline int dfs1(int u,int f,ll &ans,ll &ans1)
{
	int cnt=0;
	for(int i=head[u];i!=-1;i=e[i].next)
	{
		int v=e[i].to;
		if(v==f) continue;
		int val=e[i].val;
		int t=dfs1(v,u,ans,ans1);
		cnt+=t;
		if(t&1) ans1+=(ll)val;
		ans+=(ll)min(n-t,t)*(ll)val; 
	}
	return cnt+1;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&k);
		n=2*k;
		for(int i=0;i<=n;i++) head[i]=-1;
		tot=0;
		int x,y,z;
		for(int i=1;i<n;i++)
		{
			scanf("%d%d%d",&x,&y,&z);
			add(x,y,z);add(y,x,z);
		}
		ll ans=0,ans1=0;
		dfs1(1,0,ans,ans1);
		cout<<ans1<<" "<<ans<<endl;
	}
}

努力加油a啊,(o)/~

发布了414 篇原创文章 · 获赞 23 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/starlet_kiss/article/details/104115085