• 树的重心学习


    知识:

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

    树的重心的性质:

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

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

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

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

    会议 - 洛谷

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

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

    树的重心的求法:

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

    作为重心。

    具体看代码。

    代码:

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. const int N = 1e5 + 10;
    7. int n;
    8. vector<int> g[N];
    9. bool vis[N];
    10. int ans = 1 << 30;
    11. int dis[N], res;
    12. queue<int> q;
    13. int f[N];
    14. int dfs(int u) { // 返回值为子树的结点数
    15. vis[u] = true;
    16. int sum = 1; // 记录子树
    17. int size = 0; // 存放子树中节点数最大
    18. for(int i = 0; i < g[u].size(); i ++ ) {
    19. int j = g[u][i];
    20. if(!vis[j]) {
    21. int s = dfs(j);
    22. sum += s;
    23. size = max(size, s); // 比较所有下子树最大节点数
    24. }
    25. }
    26. ans = min(ans, max(size, n - sum)); // 和上子树比较求取最大子树结点数
    27. f[u] = max(size, n - sum); // f[u] 存放u结点最大子树结点数
    28. return sum;
    29. }
    30. void bfs(int start) {
    31. q.push(start);
    32. vis[start] = true;
    33. while(!q.empty()) {
    34. auto t = q.front();
    35. q.pop();
    36. for(int i = 0; i < g[t].size(); i ++ ) {
    37. int j = g[t][i];
    38. if(!vis[j]) {
    39. vis[j] = true;
    40. dis[j] = dis[t] + 1;
    41. q.push(j);
    42. }
    43. }
    44. }
    45. }
    46. int main() {
    47. cin >> n;
    48. for(int i = 1; i < n; i ++ ) {
    49. int a, b; cin >> a >> b;
    50. g[a].push_back(b);
    51. g[b].push_back(a);
    52. }
    53. dfs(1);
    54. memset(vis, false, sizeof vis);
    55. int st = N, start = 0;
    56. for(int i = 1; i <= n; i ++ ) { //比较每个点最大子树结点数, 若有两个重心取编号小的
    57. if(st > f[i]) {
    58. st = f[i];
    59. start = i;
    60. }
    61. else if(st == f[i]) {
    62. if(i < start) start = i;
    63. }
    64. }
    65. bfs(start); //bfs求距离和
    66. for(int i = 1; i <= n; i ++ ) {
    67. res += dis[i];
    68. }
    69. cout << start << ' ' << res << endl;
    70. return 0;
    71. }

  • 相关阅读:
    【Java力扣《代码随想录》】第4章链表63-69题(leetcode题号203+707+206+24+19+面试题02.07+142)
    考研过程中遇到学习焦虑怎么办--缓解学习焦虑的神奇方法
    依赖项安全检测新利器:Scorecard API
    过去式-ed的发音规则
    render和jsx
    第十节:继承【java】
    SpringBoot整合JWT+Vue
    “揭秘淘宝店铺所有商品接口:一键获取海量热销宝贝信息!“
    【Linux】进程间通信 -- 共享内存
    编写根据现有代码生成流程图的IDEA插件的代码。
  • 原文地址:https://blog.csdn.net/qq_74593128/article/details/133937017