(AtCoder Beginner Contest 333)

2023-12-20 13:40:27

比赛链接:

Tasks - Toyota Programming Contest 2023#8(AtCoder Beginner Contest 333)

D - Erase Leaves

题目大概意思:

给你一个树, 问你把结点1给删除掉,最少需要删除几个点?

分析:?

假设有m个结点和结点1相连,那么要想把1给删除掉,那么就要先删除掉m-1个与1相连的节点,这样就剩1个结点和结点1相连,这样结点1就变成了叶子结点,这样就可以直接把结点1给删去了,题目让求的是最小的删除,那么把与1相连的m个节点排个序,但是我们怎么去求节点数呢?这里有一个很典型dfs的算法就是求以i为根节点 的树的节点个数 dfs(int u, int fa) 要去记录这个fa,也就是这个节点的父节点,要是不记录的话会发生死循环,父节点枚举儿子节点,儿子结点又枚举父节点,这就是死循环了,因此我们要加一个if(son == fa)continue;要注意刚开始时,1就是叶子结点这个特殊情况,那直接把1这个节点给删除就行了

代码:

#include<bits/stdc++.h>
#define y1 Y1
#define fi first
#define endl "\n"
#define se second
#define PI acos(-1)
#define int long long
#define pb(x) push_back(x)
#define PII pair<int, int>
#define Yes cout << "Yes\n";
#define No cout << "No\n";
#define YES cout << "YES\n";
#define NO cout << "NO\n";
#define _for(i, a, b) for(int i = a; i <= b; ++i)
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;

const int N = 3e5 + 10;
int n, m, ret;
string s;
vector<int>h[N];
vector<int>t;
int cnt[N];//以 i为根节点 的树的节点个数

void dfs(int u, int fa) {
	cnt[u] = 1;
	for(auto son : h[u]) {
		if(son == fa)continue;
		dfs(son, u);//回来的时候 cnt[son]已经算出来了 
		cnt[u] += cnt[son];
	}
}


signed main() {
	IOS;
	cin >> n;
	_for(i, 1, n - 1) {
		int x, y;
		cin >> x >> y;
		h[x].push_back(y);
		h[y].push_back(x);
	}
	if(h[1].size() == 1) {
		cout << 1 << endl;
		return 0;
	}
	dfs(1, 0);
	
	for(auto son : h[1]) {
		t.push_back(cnt[son]);
	}
	sort(t.begin(), t.end());
	m = h[1].size();
	
	_for(i, 0, t.size() - 2) {
		ret += t[i];
	}
	
	cout << ret + 1 << endl;//还要把1这个节点给删除 因此要+1 
	return 0;
}
/*
6
1 2
2 3
2 4
3 5
3 6
*/

文章来源:https://blog.csdn.net/m0_74304371/article/details/135103706
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。