树的重心与树的直径

也许更好的阅读体验

树的重心

树的重心的定义
找到这样一个节点,使以其作为根节点时,最大的子树所含节点数最少

解决方法很简单,随便扯一个节点作为根节点,然后算一个点时考虑完所有儿子后再考虑一下父亲作为子树的答案即可

两种打法

int dfs (int x,int fa,int m)
{
    son[x]=1,ms[x]=0;//ms max_num_of_son
    int tans=2000;
    for (int e=head[x];e;e=nxt[e]){
        if (to[e]==fa||vis[to[e]])  continue;
        int t=dfs(to[e],x,m);
        if (ms[tans]>ms[t]) tans=t;
        son[x]+=son[to[e]];
        ms[x]=max(ms[x],son[to[e]]);
    }
    ms[x]=max(ms[x],m-son[x]);
    if (ms[tans]>ms[x]) tans=x;
    return tans;
}

int ans;
void dfs (int x,int fa,int m)
{
    son[x]=1,ms[x]=0;
    for (int e=head[x];e;e=nxt[e]){
        if (to[e]==fa||vis[to[e]])  continue;
        dfs(to[e],x,m);
        son[x]+=son[to[e]];
        ms[x]=max(ms[x],son[to[e]]);
    }
    ms[x]=max(ms[x],m-son[x]);
    if (ms[ans]>ms[x])  ans=x;
    return ans;
}

树的直径

求树中最长的一条路径
求法也不难,考虑一个点作为直径拐弯的点
记下最大路径和次大路径
比较所有节点的两者之和即可

实现的话只需存下最大路径,然后比较当前路径加上最大路径即可
即看看当前路径是否是次大路径或者更大的路径

void dfs(int x,int fa) {
    f[x]=1;
    for (int e=head[x];e;e=nxt[e]){
        if (to[e]==fa)  continue;
        dfs(to[e],x);
        ans=max(ans,f[x]+f[to[e]]+w[e]);
        f[x]=max(f[x],f[to[e]]+w[e]);
    }
}

如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧

猜你喜欢

转载自www.cnblogs.com/Morning-Glory/p/11481659.html