树的重心总结

树的重心

一、定义

树的某个节点,当去掉该节点后,树的各个连通分量中,节点数最多的连通分量其节点数达到最小值;

二、性质

  1. 以树的重心为根时,所有子树的大小都不超过整棵树大小的一半。
  2. 树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么到它们的距离和一样。
  3. 把两棵树通过一条边相连得到一棵新的树,那么新的树的重心在连接原来两棵树的重心的路径上。
  4. 在一棵树上添加或删除一个叶子,那么它的重心最多只移动一条边的距离。

三、求法

用搜索,搜索出以每个结点为根节点的子树上的节点个数,为子联通分量,则其的父连通分量为总个数减去子联通分量,再找到最小值即可;

四、代码

#include 
#include 
#include 
#define MAXN 105
using namespace std;
int n, dp[MAXN], dp1[MAXN], ans = 2147483647, ans1[MAXN], len, sum;
bool flag[MAXN];
vector < int > g[MAXN];
void dfs(int i) {
	dp[i] = 1;
	flag[i] = true;
	for (int t = 0; t < g[i].size(); t++) {
		int v = g[i][t];
		if (!flag[v]) {
			dfs(v);
			dp1[i] = max(dp1[i], dp[v]);
			dp[i] += dp[v];
		}
	}
	dp1[i] = max(dp1[i], n - dp[i]);
	return;
}
int main() {
	scanf("%d", &n);
	for (int i = 1; i < n; i++) {
		int x, y;
		scanf("%d %d", &x, &y);
		g[x].push_back(y);
		g[y].push_back(x);
	}
	dfs(1);
	for (int i = 1; i <= n; i++) {
		if (dp1[i] < ans) {
			ans = dp1[i];
			len = 1;
			ans1[len] = i;
		} else if (dp1[i] == ans) {
			ans1[++len] = i;
		}
	}
	printf("%d\n", len);
	for (int i = 1; i <= len; i++) {
		printf("%d\n", ans1[i]);
	}
	return 0;
}

你可能感兴趣的:(数据结构,数据结构)