关于树的重心

(由于本人太菜所以最近一直在补一些基础算法……)

求树的重心的基本思想就是从每个节点出发分别遍历一遍树,统计max_part,其中能够使得max_part最小的就是树的重心

另外:一棵有根树至多有两个重心,这个结论好像有些题可以用(比如BZOJ4337,不过那个数据太水只有50(什么暴力乱搞都能过去),但据高三的DZYO神仙说数据可以出到1e6)

大部分的解释都在代码里面(其实没有什么好解释的……我解释了下各个变量的意思)

/*
树的重心定义:对于一个树中节点x,当我们删去它时会将原来的树分割成若干个不相连的部分,其中每个部分都是一颗子树。
设max_part表示这些部分中最大的一棵子树,若删去节点x能够使得max_part最小,则称这个点为树的重心 
*/
void Dfs(int x){
    /*
    v[i]:遍历的时候打标记 
    size[i]:删去x后以i为根的子树的大小
    max_part:删去x之后大小最大的子树的大小
    pos:搜索到现在使得max_part最小的节点 
    ans:搜到现在max_part的最小值 
    */ 
    v[x]=1; size[x]=1;
    int max_part=0;
    for(register int i=head[x];i;i=nxt[i]){
        int u=ver[i];
        if(v[y])continue;
        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;
        pos=x;
    }
}

参考资料:李煜东《算法竞赛进阶指南》

猜你喜欢

转载自www.cnblogs.com/kma093/p/9747300.html