我汤姆回来了(树和图的深度优先遍历(树的重心))(10/11)

发布时间 2023-10-11 17:34:12作者: 敲代码的6
#include<iostream>
#include<cstring>
using namespace std;
const int N = 100010; const int M = N * 2;//可能多次节点重复,所以开大
int n; int e[M], ne[M], h[N], idx = 0;
bool st[N]; int ans = N;//记录最后最小值答案
//单链表的连接,不同点就是头结点有多个
void add(int a, int b) {
    e[idx] = b; ne[idx] = h[a]; h[a] = idx++;
}

int dfs(int u)
{
    st[u] = true; int sum = 0; int size = 0;
    for (int i = h[u]; i != -1; i = ne[i]) {//遍历节点
        int j = e[i];
        if (st[j]) continue;
        int s = dfs(j);//节点没被遍历过,进行深搜,返回节点个数,一条链
        size = max(size, s);//记录去掉该节点后连通块最大值
        sum += s;//求链的全部节点
    }
    size = max(size, n - sum - 1);
    ans = min(ans, size);
    return sum + 1;//返回节点个数加自己
}

int main()
{
    scanf("%d", &n);

    memset(h, -1, sizeof h);

    for (int i = 0; i < n - 1; i++)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b), add(b, a);
    }

    dfs(1);

    printf("%d\n", ans);

}