Tree Cutting

本文介绍了一种算法,用于在给定一棵包含不超过10,000个节点的无向树时,确定哪些节点的移除可以使剩余的每棵树的节点数都小于总数的一半。通过深度优先搜索,维护子树节点数的最大值和总和,从而找到符合条件的节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一棵无向树,结点为n(<=10,000),删除哪些结点可以使得新图中每一棵树结点小于n/2。
在遍历树的过程中,访问每个node,维护两个值:
所有子树的结点数的最大值childmax
所有子树(这里包括node)的结点数之和sum。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
#define mst(s, t) memset(s, t, sizeof(s))
const int INF = 0x3f3f3f3f;
const int maxn = 10010;
vector<int> G[maxn];
int ans[maxn], num, n;
int dfs(int node, int father){
    int sum = 1, childmax = 0;   //若是叶子结点则return sum=1,否则求其子树(包括自己)的总结点数
    for(int i=0; i<G[node].size(); i++){
        if(G[node][i] == father)continue; //因为是树结构,这里可以在无向时避免遍历成环 
        int sum_son = dfs(G[node][i], node);
        childmax = max(sum_son, childmax);//所有子树的结点数的最大值
        sum += sum_son;//sum:node的子树的结点数和
    }
    childmax = max(childmax, n-sum);
    if(childmax <= n/2){
        /*
         * 当node结点的孩子结点的结点数最大为Sum,若Sum<=n/2,则该点符合条件
         * 因为去掉node后,任意子树结点数<=n/2, max()保证其非子树结点和仍<=n/2
         * 故该点满足条件
        */
        ans[num++] = node;
    }
    return sum;
}
int main() 
{
    //freopen("in.txt", "r", stdin);
    scanf("%d", &n);
    for(int i=0; i<n-1; i++){
        int a, b;
        scanf("%d%d", &a, &b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
    num = 0;
    int tmp = dfs(1, 0);
    //cout << n << "==" << tmp << endl; //验证
    sort(ans, ans+num);
    if(num){
        for(int i=0; i<num; i++){
            printf("%d\n", ans[i]);
        }
    }else{
        printf("NONE\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值