Tasks - Toyota Programming Contest 2023#8(AtCoder Beginner Contest 333)
给你一个树, 问你把结点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
*/