总结收获
1. 这种有很多很多操作,求最终状态的问题:先通过一些操作把它转化为最最最基本的形式(不用考虑操作,只需要考虑它的**最基本的形式**)。
2. dfs删除满足条件的点。==这个需要对树的结构有很清晰的认识,同时需要在赛场上的思维灰常清晰!!!==
题目
- E. Buds Re-hanging
- 题意:一棵树,树的芽满足以下条件,每次可以剪掉一棵芽(去掉芽和它的父亲中间的边)放在其他任意节点上,求任意次操作之后叶子节点的数目的最小值。
芽的定义:
- 题解:
- 这种有很多很多操作,求最终状态的问题:先通过一些操作把它转化为最最最基本的形式(不用考虑操作,只需要考虑它的最基本的形式)。
- dfs删除满足条件的点。这个需要对树的结构有很清晰的认识,同时需要在赛场上的思维灰常清晰!!!
- 代码:
#include <bits/stdc++.h>
#define dbg(x) cout << #x << "===" << x << endl
using namespace std;
const int N = 2e5 + 5;
int n, u, v;
int vis[N];
set<int> g[N];
int ans;
void init() {
ans = n;
for (int i = 0; i <= n; i++) g[i].clear(), vis[i] = 1;
}
void dfs(int x, int fa) {
int cnt = 0, vc = 0;
for (auto i : g[x]) {
if (i == fa) continue;
dfs(i, x);
cnt++;
if (vis[i] == 2) vc++;
}
if (x > 1 && g[x].size() > 1 && cnt - vc > 0) vis[x] = 2, ans -= 2;
}
signed main() {
int T;
cin >> T;
while (T--) {
scanf("%d", &n);
init();
for (int i = 1; i < n; i++) {
scanf("%d%d", &u, &v);
g[u].insert(v);
g[v].insert(u);
}
dfs(1, 0);
for (auto i : g[1]) {
if (vis[i] == 1) {
ans--;
break;
}
}
cout << ans << endl;
}
return 0;
}