zoukankan      html  css  js  c++  java
  • 树的重心

    树的重心

    定义

    树上一节点,且满足它的最大子树的节点数最小。

    性质

    (ps.) 性质网上都有,但是没有一篇博客进行了证明。此后的儿子节点指重心与子树相连的节点。

    (1.) 删除重心后所得的所有子树,节点数不超过原树的 (frac{1}{2}),一棵树最多有 (2) 个重心;

    证明:这是树的重心的基本性质,如果重心的一个子树的节点数大于 (frac{1}{2}) 那么重心的这个子儿子肯定会比重心更有资格当重心,矛盾。

    (2.) 树中所有节点到重心的距离之和最小,如果有两个重心,那么他们距离之和相等;

    证明:这种情况只有可能是 (2) 个重心之间连边,并且重心 (1) 的最大子树是以重心 (2) 为儿子的子树,重心 (2) 的最大子树也是以重心 (1) 为儿子的子树。 (2) 个子树大小相等,各为 (frac{n}{2})

    (3.) 两个树通过一条边合并,新的重心在原树 (2) 个重心的路径上;

    证明,这个可以用反证法。假设我们取极限情况。一个重心连的最大子树大小为 (frac{n}{2}),另一个大小为 (1)。因为如果新的重心不在 (2) 个重心之间,它也会在最大的子树的儿子节点。那么此时这个儿子所连的子树总大小(除了返祖的子树)为 (frac{n - 1}{2}) 那么可以可以简单容斥一下推出返祖的子树大小为 (n + 1 - frac{n - 1}{2}) 也就是 (frac{n + 3}{2}) 大于 (frac{n}{2}) 所以矛盾。

    (4.) 树删除或添加一个叶子节点,重心最多只移动一条边;

    证明:这个很简单,因为一个节点被修改最多只会改变一个子树的大小。所以重心最多只能移动一位。

    实现

    首先是根据他的定义直接用 (Dfs) 实现。

    int size[maxn], val[maxn], f[maxn];//size[i] 表示 i 的子树大小,val[i] 表示 i 节点的权值,f[i] 表示 i 为根节点的最大子树。
    void Dfs(int x, int fa) {
        size[x] = val[x], f[x] = 0;
        Next(i, x) { int v = e[i].to;
            if(v == x) continue;
            Dfs(v, x);
            size[x] += size[v];
            f[x] = max(f[x], size[v]);
        } f[x] = max(f[x], n - size[now]);//要考虑它父节点引出去的
        if(f[x] < f[ans]) ans = x;
    }
    
  • 相关阅读:
    msp430时钟小结
    JDBC第一天连接池案例
    maltab几个常见的问题
    qt 获取天气的接口
    Qt Style Sheets制作UI特效
    qt 在指定区域添加图片
    qt 设置背景图片
    linux下mysql数据库的学习
    qt文本编辑器
    C++小游戏:扑克牌21点
  • 原文地址:https://www.cnblogs.com/Flash-plus/p/13834034.html
Copyright © 2011-2022 走看看