树的重心(树的dfs遍历)

给定一颗树,树中包含 n� 个结点(编号 1∼n1∼�)和 n−1�−1 条无向边。

请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。

重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。

输入格式

第一行包含整数 n�,表示树的结点数。

接下来 n−1�−1 行,每行包含两个整数 a� 和 b�,表示点 a� 和点 b� 之间存在一条边。

输出格式

输出一个整数 m�,表示将重心删除后,剩余各个连通块中点数的最大值。

数据范围

1≤n≤105

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector> 
#include <map>
#include <stack>
#include <queue>
#include <set>
#include <unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const ll maxx = 1e9;
int n, m, T;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1.0);
int dx[4] = { 0 , 1 , -1 , 0 }, dy[4] = { 1 , 0 , 0 , -1 };
int h[N], e[N * 2], ne[N * 2];//h邻接表储存树, 有n个节点//e储存元素//ne储存列表的next值

int idx;//单链表指针
int ans = N;//表示重心的所有的子树中,最大的子树的节点数
bool st[N];//记录节点是否被访问过,被访问过就标记为true

void add(int a, int b)//邻接表//a对应单链表中插入b,a作为根
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
//返回以u为根的子树中的节点的个数,包括u节点 
int dfs(int u)
{
    int res = 0;
    st[u] = true;//标记访问过的u节点
    int sum = 1;//储存以u为根的树的节点数,包括u,
    //访问u的每个子节点
    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!st[j])
        {
            int s = dfs(j);//u节点的单棵子树点数
            res = max(res, s);//记录最大联通子图的节点数
            sum += s;
        }
    }
    res = max(res, n - sum);//选择u节点为重心 , 最大的连通子图节点数
    ans = min(res, ans);//遍历过的假设重心中, 最小的最大联通子图的节点数
    return sum;
}
void solve()
{
    memset(h, -1, sizeof(h));//初始化节点,-1表示尾结点
    cin >> n;
    //树不存在环,对于有n个节点的树,必定是n - 1条边
    for (int i = 0; i < n - 1; i++)
    {
        int a, b;
        cin >> a >> b;
        add(a, b), add(b, a);//无向图
    }
    dfs(1);//任选一个节点就行//因为是无向图
    cout << ans << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    //cin >> T;
    //while (T--)
    //{
        solve();
    //}
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tang_7777777

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值