acwing 846 树的重心 (树的深度遍历)

题面

在这里插入图片描述

题解

在这里插入图片描述

  1. 如图,树的重心就是一个节点,如果将这个节点删除,剩余连通块中点数最大的最小值,样例中树的重心是4,要知道,树的重心是不唯一的,但是值是唯一的
  1. 我们可以用树的深搜,dfs记录以u为根节点子树的大小(包括自己),然后就可以求出删除这个点以后所有的连通块(以这个点为根节点的所有子树,整棵树删除以这个点为根节点的树),在这些中去一个最大,然后在最后更新一下最大的最小就是答案

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 1e5 + 10;

int n;
int h[N], e[N * 2], ne[N * 2], idx;
bool st[N];
int cnt = N;  //最大值的最小值

//添加一条a-->b的边
void add(int a, int b) {
    
    
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx++;
}

//返回以u为根节点子树的大小(包括自己)
int dfs(int u) {
    
    
    st[u] = true;   //表示点u已经被遍历过了
    int s = 1; //根节点的数量
    int res = 0; //剩余连通块中点数最大值
    for (int i = h[u]; i != -1; i = ne[i]) {
    
    
        int j = e[i];
        if (!st[j]) {
    
    
            int t = dfs(j);
            res = max(res, t);
            s += t;  //加上自己的子树
        }
    }
    res = max(res, n - s);
    cnt = min(res, cnt);
    return s;
}


int main() {
    
    

    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    memset(h, -1, sizeof h);

    cin >> n;

    for (int i = 1; i < n; i++) {
    
    
        int a, b;
        cin >> a >> b;
        add(a, b), add(b, a);
    }

    dfs(1);

    cout << cnt << endl;

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44791484/article/details/114394823