树的重心学习

编程入门 行业动态 更新时间:2024-10-26 14:28:41

树的<a href=https://www.elefans.com/category/jswz/34/1719134.html style=重心学习"/>

树的重心学习

知识:

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

树的重心的性质:

1.一个树最多只有1个或2个重心。如果有两个重心,它们必定相邻且在树的最长路径中间位置。

2.把两个树通过一条边相连得到一个新的树,那么新的树的重心在连接原来两个树的重心的路径上。

3.树中所有点到某个点的距离和中,到重心的距离和是最小的;

4.把一个树添加或删除一个叶子,那么它的重心最多只移动一条边的距离。

会议 - 洛谷

于是乎这个题就可以这样解决:

先把树的重心求出来, 算出所有其他结点到树的重心的距离之和。

树的重心的求法:

dfs遍历每一个点,求取每个点作为"重心“的最大子树的节点数,然后取最小的那个

作为重心。

具体看代码。

代码:

#include <iostream>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;const int N = 1e5 + 10;
int n;
vector<int> g[N];
bool vis[N];
int ans = 1 << 30;
int dis[N], res;
queue<int> q;
int f[N];int dfs(int u) { // 返回值为子树的结点数vis[u] = true;int sum = 1; // 记录子树int size = 0; // 存放子树中节点数最大for(int i = 0; i < g[u].size(); i ++ ) {int j = g[u][i];if(!vis[j]) {int s = dfs(j);sum += s;size = max(size, s); // 比较所有下子树最大节点数}}   ans = min(ans, max(size, n - sum)); // 和上子树比较求取最大子树结点数f[u] = max(size, n - sum); // f[u] 存放u结点最大子树结点数  return sum;
}void bfs(int start) {q.push(start);vis[start] = true;while(!q.empty()) {auto t = q.front();q.pop();for(int i = 0; i < g[t].size(); i ++ ) {int j = g[t][i];if(!vis[j]) {vis[j] = true;dis[j] = dis[t] + 1;q.push(j);}}}
}int main() {cin >> n;for(int i = 1; i < n; i ++ ) {int a, b; cin >> a >> b;g[a].push_back(b);g[b].push_back(a);}dfs(1);memset(vis, false, sizeof vis);int st = N, start = 0;for(int i = 1; i <= n; i ++ ) { //比较每个点最大子树结点数, 若有两个重心取编号小的if(st > f[i]) {st = f[i];start = i;}else if(st == f[i]) {if(i < start) start = i;}}bfs(start); //bfs求距离和for(int i = 1; i <= n; i ++ ) {res += dis[i];}cout << start << ' ' << res << endl;return 0;
}

更多推荐

树的重心学习

本文发布于:2023-12-07 10:10:20,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1670944.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:重心

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!