Commit 454d0a53 authored by ouuan's avatar ouuan
Browse files

fix(centroid): move tree-misc to tree-centroid and update it

parent 71172ca2
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
author: Ir1d, TrisolarisHD, LucienShui, Anguei

## 定义

对于树上的每一个点,计算其所有子树中最大的子树节点数,这个值最小的点就是这棵树的重心。

(这里以及下文中的“子树”都是指无根树的子树,即包括“向上”的那棵子树,并且不包括整棵树自身。)

## 性质

以树的重心为根时,所有子树的大小都不超过整棵树大小的一半。

树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么到它们的距离和一样。

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

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

## 求法

在 DFS 中计算每个子树的大小,记录“向下”的子树的最大大小,利用总点数 - 当前子树(这里的子树指有根树的子树)的大小得到“向上”的子树的大小,然后就可以依据定义找到重心了。

???+note "参考代码"
    ```cpp
    void getCentroid(int u,int fa)
    {
      siz[u]=1;
      wt[u]=0;
      for (int i=head[u];~i;i=nxt[i])
      {
        int v=to[i];
        if (v!=fa)
        {
          getCentroid(v,u);
          siz[u]+=siz[v];
          wt[u]=max(wt[u],siz[v]);
        }
      }
      wt[u]=max(wt[u],n-siz[u]);
      if (rt==0||wt[u]<wt[rt]) rt=u; // rt 为重心编号
    }
    ```

## 参考

 <http://fanhq666.blog.163.com/blog/static/81943426201172472943638/> 

 <https://www.cnblogs.com/zinthos/p/3899075.html> 

docs/graph/tree-misc.md

deleted100644 → 0
+0 −65
Original line number Diff line number Diff line
## 树的重心

### 定义

以树的重心为根时,所有的子树(不算整个树自身)的大小都不超过整个树大小的一半。

找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心。

删去重心后,生成的多棵树尽可能平衡。

### 性质

树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么他们的距离和一样。

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

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

### 求法

树的重心可以通过简单的两次搜索求出。

1.  第一遍搜索求出以每个节点为根的子树中结点数量 $sz_{u}$ 
2.  第二遍搜索找出使 $\max_{v\in\operatorname{son}(u)}\{n-sz_{u},sz_{v}\}$ 最小的节点 $u$ 。

实际上这两步操作可以在一次遍历中解决。对节点 u 的每一个儿子 v 递归处理,然后以 $sz_{v}$ 更新 $u$ 的子节点子树节点数最大值,处理完所有子结点后,判断 u 是否为重心。

(代码来自叉姐)

```cpp
struct CenterTree {
  int n;
  int ans;
  int siz;
  int son[maxn];
  void dfs(int u, int pa) {
    son[u] = 1;
    int res = 0;
    for (int i = head[u]; ~i; i = edges[i].next) {
      int v = edges[i].to;
      if (v == pa) continue;
      dfs(v, u);
      son[u] += son[v];
      res = max(res, son[v]);
    }
    res = max(res, n - son[u]);
    if (res < siz) {
      ans = u;
      siz = res;
    }
  }
  int getCenter(int x) {
    ans = 0;
    siz = INF;
    dfs(x, -1);
    return ans;
  }
}
```

## 参考

 <http://fanhq666.blog.163.com/blog/static/81943426201172472943638/> 

 <https://www.cnblogs.com/zinthos/p/3899075.html> 
+4 −4
Original line number Diff line number Diff line
@@ -297,13 +297,13 @@ nav:
    - 树上问题:
      - 树基础: graph/tree-basic.md
      - 最近公共祖先: graph/lca.md
      - 树的其他问题: graph/tree-misc.md
      - 树哈希: graph/tree-hash.md
      - 树的重心: graph/tree-centroid.md
      - 树链剖分: graph/hld.md
      - 树上启发式合并: graph/dsu-on-tree.md
      - 虚树: graph/virtual-tree.md
      - 树分治: graph/tree-divide.md
      - 动态树分治: graph/dynamic-tree-divide.md
      - 虚树: graph/virtual-tree.md
      - 树上启发式合并: graph/dsu-on-tree.md
      - 树哈希: graph/tree-hash.md
    - 矩阵树定理: graph/matrix-tree.md
    - 有向无环图: graph/dag.md
    - 拓扑排序: graph/topo.md