cf1566E. Buds Re-hanging(图论&dfs删除满足条件的点)

总结收获

1. 这种有很多很多操作,求最终状态的问题:先通过一些操作把它转化为最最最基本的形式(不用考虑操作,只需要考虑它的**最基本的形式**)。
2. dfs删除满足条件的点。==这个需要对树的结构有很清晰的认识,同时需要在赛场上的思维灰常清晰!!!==

题目

  1. E. Buds Re-hanging
  2. 题意:一棵树,树的芽满足以下条件,每次可以剪掉一棵芽(去掉芽和它的父亲中间的边)放在其他任意节点上,求任意次操作之后叶子节点的数目的最小值。
    芽的定义:
  • 不是根
  • 不是叶子节点
  • 所有节点均为叶子节点
  1. 题解
    1. 这种有很多很多操作,求最终状态的问题:先通过一些操作把它转化为最最最基本的形式(不用考虑操作,只需要考虑它的最基本的形式)。
    2. dfs删除满足条件的点。这个需要对树的结构有很清晰的认识,同时需要在赛场上的思维灰常清晰!!!
  2. 代码
/*
链接:https://codeforces.ml/contest/1566/problem/E
题解链接:https://codeforces.ml/blog/entry/94803
1. 先转化为最最最普遍的情况,然后再找规律进行处理。
2. 黑,我的方法是对的呀
>>>>>>>>>>>>>>>>>>>>>>>>>...总结:思路要清晰,多刷题,这些东西的结构都给理清楚,然后就可以更快a题了
*/
#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];  // 2:芽;1:叶子节点;-1:没有这个节点;0:未标记
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) {
    // if (g[x].size() == 1 && x > 1) vis[x] = 1;
    int cnt = 0, vc = 0;
    // bool f = true;
    for (auto i : g[x]) {
        if (i == fa) continue;
        dfs(i, x);
        // if (vis[i] != 1) f = false;
        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 << ">>>>>>>";
        // cout << endl;
        // for (int i = 1; i <= n; i++)
        // cout << ">>>>>>>" << i << ' ' << vis[i] << endl;
        // if (vis[i] == 2) cout << ">>>>>>>>>>>" << i << endl;
        cout << ans << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值