F. Gardening Friends(树的直径)

Problem - 1822F - Codeforces

F. Gardening Friends(树的直径)_第1张图片

两位朋友Alisa和Yuki在他们的花园里种了一棵有n个顶点的树。树是一个无向图,没有循环、回路或多重边。这棵树中的每条边都有一个长度为k。最初,顶点1是树的根。

Alisa和Yuki种植这棵树不仅仅是为了好玩,而是想要卖掉它。该树的成本定义为树上所有顶点中从根到顶点的最大距离。两个顶点u和v之间的距离是沿着从u到v的路径上边的长度之和。

女孩子们学过园艺课程,所以她们知道如何修改树。Alisa和Yuki可以花费c枚硬币将树的根移动到当前根的其中一个邻居。这个操作可以执行任意次数(可能为零)。请注意,树的结构保持不变;唯一的变化是哪个顶点是根。

女孩们想以最大的利润卖出这棵树。利润定义为成本减去操作总成本。利润是树的成本减去操作的总成本。

帮助女孩们,找出通过对树进行任意次数的操作(可能为零)所能获得的最大利润。

输入

第一行包含一个整数t(1≤t≤104)——测试用例的数量。

接下来是每个测试用例的描述。

每个测试用例的第一行包含整数n、k和c(2≤n≤2⋅105;1≤k,c≤109) ——树中顶点的数量,每条边的长度以及操作的成本。

测试用例的下面n−1行包含一对整数ui和vi(1≤ui,vi≤n)——图的边。这些边形成一棵树。

所有测试用例中n的值的总和不超过2×105。

输出

对于每个测试用例,输出一个整数——Yuki和Alisa可以获得的最大利润。

Example

Input

Copy

 
  

4

3 2 3

2 1

3 1

5 4 1

2 1

4 2

5 4

3 4

6 5 3

4 1

6 1

2 6

5 1

3 2

10 6 4

1 3

1 9

9 7

7 6

6 4

9 2

2 8

8 5

5 10

Output

Copy

2
12
17
32

题解:

这道题考察树的直径。

树的直径即树中两个最远点之间的路径。

树的直径有一个性质,距离任何一个点最远的点是直径两个端点的其中一个。

通过这个特点,我们可以通过两次DFS求出树的直径的两个端点,

然后分别以这两个端点为根,我们可以求出,每个点距离两个端点的距离,这两个距离之一就是此时距离最远的点的距离

对于代价,我们可以从1节点dfs求得

遍历所有点(此时的最远距离*k - 代价)的最大值即为答案

#include 
#include 
#include 
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
 #define int long long
typedef pair PII;
typedef unsigned long long ULL;
const int N = 4e5 + 10;
int mod = 1e9 + 7;
vector p[N];
int n,k,c;
int dep[N];
int cost[N];
int f,ff;
int dep1[N];
void dfs(int u,int fa)
{
	for(auto ne:p[u])
	{
		if(ne == fa)
		continue;
		cost[ne] = cost[u] + 1;
		dfs(ne,u);
	}
} 
void dfs1(int u,int fa)
{
	for(auto ne:p[u])
	{
		if(ne == fa)
		continue;
		dep[ne] = dep[u] + 1;
		if(dep[ne] > dep[f])
		{
			f = ne;
		}
		dfs1(ne,u);
	}
}
void dfs2(int u,int fa)
{
	for(auto ne:p[u])
	{
		if(ne == fa)
		continue;
		dep1[ne] = dep1[u] + 1;
		if(dep1[ne] > dep1[ff])
		{
			ff = ne;
		}
		dfs2(ne,u);
	}
}
void solve()
{
	cin >> n >> k >> c;
	for(int i = 1;i < n;i++)
	{
		int l,r;
		cin >> l >> r;
		p[l].push_back(r);
		p[r].push_back(l);
	}
	cost[1] = 0;
	dfs(1,0);
	
	dep[1] = 0;
	dfs1(1,0);
	
	dep1[f] = 0;
	dfs2(f,0);
	
	dep[ff] = 0;
	dfs1(ff,0);
	
	int ans = 0;
	for(int i = 1;i <= n;i++)
	{
		ans = max(max(dep[i],dep1[i])*k - cost[i]*c,ans);
	}
	cout << ans <<"\n";
	
	for(int i = 1;i <= n;i++)
	{
		p[i].clear();
		dep[i] = 0;
	}
}
signed main()
{
	ios::sync_with_stdio(0 );
	cin.tie(0);cout.tie(0);
	int t = 1;
	cin >> t;
	while(t--)
	{
		solve(); 
	}
}

 

你可能感兴趣的:(算法)