当前位置: 首页 > article >正文

【Codeforces】CF 2019 E

Tree Pruning

#差分 #树形结构

题目描述

You are given a tree with n n n nodes, rooted at node 1 1 1. In this problem, a leaf is a non-root node with degree 1 1 1. In one operation, you can remove a leaf and the edge adjacent to it (possibly, new leaves appear). What is the minimum number of operations that you have to perform to get a tree, also rooted at node 1 1 1, where all the leaves are at the same distance from the root?

输入格式

Each test contains multiple test cases. The first line contains the number of test cases t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1t104). The description of the test cases follows. The first line of each test case contains a single integer n n n ( 3 ≤ n ≤ 5 ⋅ 1 0 5 3 \leq n \leq 5 \cdot 10^5 3n5105) — the number of nodes. Each of the next n − 1 n-1 n1 lines contains two integers u u u, v v v ( 1 ≤ u , v ≤ n 1 \leq u, v \leq n 1u,vn, u ≠ v u \neq v u=v), describing an edge that connects u u u and v v v. It is guaranteed that the given edges form a tree. It is guaranteed that the sum of n n n over all test cases does not exceed 5 ⋅ 1 0 5 5 \cdot 10^5 5105.

输出格式

For each test case, output a single integer: the minimum number of operations needed to achieve your goal.

样例 #1

样例输入 #1

3
7
1 2
1 3
2 4
2 5
4 6
4 7
7
1 2
1 3
1 4
2 5
3 6
5 7
15
12 9
1 6
6 14
9 11
8 7
3 5
13 5
6 10
13 15
13 6
14 12
7 2
8 1
1 4

样例输出 #1

2
2
5

解法

解题思路

对于每一个节点,我们考虑留下它对于答案的贡献,如下图所示,我要考虑留下 2 2 2号节点:

在这里插入图片描

那么 2 2 2号点连着的最链是 2 − 4 − 6 、 2 − 5 2-4-6、2-5 24625,也就是说留着 2 2 2号点对深度为 d e p t h 2 − d e p t h m a x s o n 2 depth_2-depth_{maxson_2} depth2depthmaxson2有贡献。 也就是说,分别留着 5 , 4 , 6 5,4,6 5,4,6作为叶子节点的时候,都可以留着 2 2 2号节点,而不需要删除它。

进一步的,所有节点都满足 d e p t h i − d e p t h m a x s o n i depth_i-depth_{maxson_i} depthidepthmaxsoni有贡献,因此我们就可以对这个深度 + 1 +1 +1,具体而言就是使用差分,然后求一个遍前缀和,最后枚举深度,求出最小需要删除的个数即可,即 a n s = min ⁡ { a n s , n − d e p t h i } ans = \min\{ans,n - depth_i\} ans=min{ans,ndepthi}

也就是说对于 2 2 2好点,

代码

void solve() {
	int n;
	std::cin >> n;
 
	std::vector<std::vector<int>>e(n + 1);
 
	for (int i = 1; i <= n - 1; ++i) {
		int u, v; 
		std::cin >> u >> v;
 
		e[u].emplace_back(v);
		e[v].emplace_back(u);
	}
 
	std::vector<int>deep(n + 1), maxs(n + 1);
	
	auto dfs = [&](auto&&self ,int u, int fa)->void {
		
		deep[u] = deep[fa] + 1;
		maxs[u] = deep[u];
		for (auto& v : e[u]) {
			if (v == fa) continue;
			self(self, v, u);
			maxs[u] = std::max(maxs[u], maxs[v]);
		}
		};
	
	dfs(dfs, 1, 1);
 
	int maxd = *std::max_element(deep.begin() + 1, deep.end());
 
	std::vector<int>d(n + 2);
	for (int i = 1; i <= n; ++i) {
		d[deep[i]]++;
		d[maxs[i] + 1]--;
	}
 
	std::partial_sum(d.begin() + 1, d.end(), d.begin() + 1);
	std::vector<int>prefix(n + 1);
 
	int res = n - *std::max_element(d.begin() + 1, d.end());
 
	std::cout << res << "\n";
		
	
 
}
 
signed main() {
	std::ios::sync_with_stdio(0);
	std::cin.tie(0);
	std::cout.tie(0);
 
	int t = 1;
	std::cin >> t;
 
	while (t--) {
		solve();
	}
};

http://www.kler.cn/news/334813.html

相关文章:

  • 数据治理006-数据标准的管理
  • 王道-数据结构
  • Unity Asset Store的默认下载位置及更改下载路径的方法
  • 国庆练习(Day23)
  • LeetCode 151 Reverse Words in a String 解题思路和python代码
  • GPT对话知识库——在STM32的平台下,通过SPI读取和写入Flash的步骤。
  • 网络安全概述:从认知到实践
  • Python机器学习:自然语言处理、计算机视觉与强化学习
  • c++11~c++20 结构化绑定
  • Docker 启动 Neo4j:详细配置指南和浏览器访问
  • Spring源码-AOP
  • go dlv idea 远程调试-入门级
  • 优化销售漏斗建立高效潜在客户生成策略的技巧
  • Vue 插槽全攻略:重塑组件灵活性
  • 面试知识储备-多线程
  • HTB:Ignition[WriteUP]
  • 二分搜索算法
  • 国内动态短效sk5
  • 实验5 预备实验2-配置单个的路由器
  • 《Linux从小白到高手》理论篇:一文概览常用Linux重要配置文件