当前位置: 代码迷 >> 综合 >> AcWing 846. 树的重心(模板)
  详细解决方案

AcWing 846. 树的重心(模板)

热度:10   发布时间:2024-01-29 19:18:41.0

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

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

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

输入格式

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

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

输出格式

输出一个整数m,表示重心的所有的子树中最大的子树的结点数目。

数据范围

1≤n≤105

输入样例

9
1 2
1 7
1 4
2 8
2 5
4 3
3 9
4 6

输出样例:

4

解法: 通过dfs,每次统计以某点为根的子树中点的个数的最大值,再与剩余的节点比较,得到某点所有的连通块的最大值,再在各点中找出所有的点最大值中的最小值即为答案。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5+5;
int ans = N,head[N],nxt[N*2],e[N*2],tot,n;//无向图开两倍空间
bool st[N];
void add(int u,int v) {e[tot] = v;nxt[tot] = head[u];head[u] = tot++;
}
int dfs(int u) {st[u] = true;int cnt = 0,sum = 0;for(int i=head[u];i != -1;i = nxt[i]) {int j = e[i];if(!st[j]) {int s = dfs(j);cnt = max(cnt,s);//每次统计以u为根的子树中点的个数的最大值sum += s;}}cnt = max(cnt,n - sum - 1);//与剩余的点的个数比较ans = min(ans,cnt);//比较各个最大值中的最小值return sum + 1;//返回以u为根的子树中的点的个数(加上本身)
}
int main() {cin >> n;int l,r;memset(head,-1,sizeof(head));for(int i=0;i<n;i++) {cin >> l >> r;add(l,r);add(r,l);}dfs(1);cout << ans;return 0;
}