树的重心

定义:
重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。
不妨设max_part(x)为在删除节点x后产生的子树中,最大的一颗大小。那么树的重心就是使得max_part函数取到最小的节点p就是整颗树的重心。

void dfs(int x)
{
    v[x] = 1; size[x] = 1; //设置子树的大小;
    int max_part = 0; //表示删除x后最大子树的大小;
    
    for (int i = head[x]; i; i = ne[i]) 
    {
        int y= ver[i];
        if (v[y]) continue;  //点y已经被访问过了;
        dfs(y);
        size[x] += size[y]; //从子节点更新到父节点
        max_part = max(max_part, size[y]);
    }
    max_part = max(max_part, n - size[x]);
    if (max_part < ans ) {
        ans = max_part; //全局量记录重心对应的max_part
        pos = x;  //全局量pos记录重心;
    }
}

图里联通块计数

本质上还是图着色,这里用cnt表示不同的颜色。

void dfs(int x)
{
    v[x] = cnt;
    for (int i = head[x]; i; i = ne[i]) {
        int y = ver[i];
        if (v[y]) continue;
        dfs(y);
    }
}

//依次着色森林;
for (int i = 1; i <= n; i++) {
    if (!v[i]) {
        cnt++;
        dfs(i);
    }
}

参考

  1. 算法进阶指南
  2. ACwing