Codeforces 1566E Buds Re-hanging

原题链接 Codeforces Global Round 16 E. Buds Re-hanging

首先想到,如果我们把一个buds挂到一个叶子上,那么会使得叶子总数减1
还有就是如果我们可以把这个树搞成一条链,那么总叶子数一定是最少的,就是让树“越瘦越好”。

如果原来一个buds挂在一个没有其他孩子的结点上,我们拿走这个buds之后会使得总叶子数加1,我们称这个结点为 α,如果一个buds挂在一个有其他孩子的节点上,那么拿走这个buds总叶子数不会改变,我们称这个结点为β

我们考虑把所有的buds全挂在root上,那么这样做会使结果变坏吗?当然不会

  1. 如果一个buds挂在一个β结点上,那么拿走后总叶子数不变。
  2. 如果一个buds挂在一个α结点上,那么拿走后总叶子数会加1,但是我们完全可以再搞一个buds挂在α结点上,这样就叶子总数又减少了。

全挂在root上之后,我们考虑再将其变成一条链子,怎么变呢?

首先设总结点数为nbuds数为k,那么由于所有buds全挂在了root上,那么现在的叶子数就是nk1
情况一:如果root上有一个叶子结点, 那么我们不妨把kbuds依次全挂到这个叶子节点上,那么我们挂一次少一个叶子,那么答案就是nk1k
情况二:如果root上没有叶子结点,那么我们就把k1buds都依次挂到一个bud上就行,那么答案就是nk1(k1)

代码:

// Problem: E. Buds Re-hanging
// Contest: Codeforces - Codeforces Global Round 16
// URL: https://codeforces.com/contest/1566/problem/E
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

using namespace std;

const int N = 2E5 + 10;
vector<int> g[N];
int type[N]; //0 -- root, 1 -- leaf, 2 -- bud

void dfs(int u, int fa) {
	bool leaf = false;
	for (auto v : g[u]) {
		if (v == fa) continue;
		dfs(v, u);
		if (type[v] == 1) leaf = true;
	}
	
	if (u != fa) {
		if (!leaf) type[u] = 1;
		else type[u] = 2;
	}
}

int main() {
	int _; scanf("%d", &_);
	while (_--) {
		int n;
		scanf("%d", &n);
		for (int i = 1; i <= n; i++) g[i].clear();
		memset(type, -1, sizeof type);
		
		for (int i = 1; i <= n - 1; i++) {
			int u, v;
			scanf("%d%d", &u, &v);
			g[u].push_back(v);
			g[v].push_back(u);
		}
		
		type[1] = 0;
		dfs(1, 1);
		
		bool rHas_leaf = false;
		for (auto it: g[1]) {
			if (type[it] == 1) {
				rHas_leaf = true;
				break;	
			}
		}
		
		//将所有buds直接接到根上,这样在把buds拿走接到一个leaf上只会减少一个leaf数,而不会增加leaf
		//设buds有k个,那么现在叶子节点数n - k - 1
		/*
		如果根有叶子结点,我们选择将k个buds顺次接到这个叶子结点上,接一次减少1,所以答案n - k - 1 - k
		如果根没有叶子结点,那么将其他buds接到其中一个bud上去,那么答案n - k - 1 - (k - 1)
		*/		
		int k = 0;
		for (int i = 1; i <= n; i++) {
			if (type[i] == 2) k += 1;
		}
		
		if (rHas_leaf) printf("%d\n", n - 2 * k  - 1);
		else printf("%d\n", n - 2 * k);
	}
	
    return 0;
}
posted @   Xxaj5  阅读(76)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示