点分治学习:树的重心(质心)

树的重心定义

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

dfs一遍就可以找到树的重心

void dfs(int u,int fa)
{
    //vis[u]=true,
    sizx[u]=1;
    max_part[u]=0;
    for(int i=head[u]; ~i; i=tr[i].nex)
    {
        int v=tr[i].to;
        if(v==fa)
        {
            continue;
        }
        dfs(v,u);
        sizx[u]+=sizx[v];
        max_part[u]=max(max_part[u],sizx[v]);
    }
    max_part[u]=max(max_part[u],n-sizx[u]);//换根法
    ans=min(max_part[u],ans);
}

先从节点1,遍历到最后节点,如果当没有叶子节点,以该节点为根,查找他的子树的节点数量
max_part[u]=max(max_part[u],n-sizx[u]),在回溯的时候,u的孩子节点v是以u为根的max_part[i]的一部分,比较max_part[i]和sizx[v],得到一部分最大值,最后比较以哪一个为根所得到的最大子树最少节点

求树的重心:
题目链接:Balancing Act
AC代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
//求树的重心
const int maxn=1e5+5;
struct node
{
    int to,nex;
} tr[maxn*4];
int n,ans;
int max_part[maxn];//子树最大部分
int sizx[maxn],cnt;//代表节点数量
int head[maxn];
void add(int u,int v)
{
    tr[cnt].to=v;
    tr[cnt].nex=head[u];
    head[u]=cnt++;
}
void dfs(int u,int fa)
{
    //vis[u]=true,
    sizx[u]=1;
    max_part[u]=0;
    for(int i=head[u]; ~i; i=tr[i].nex)
    {
        int v=tr[i].to;
        if(v==fa)
        {
            continue;
        }
        dfs(v,u);
        sizx[u]+=sizx[v];
        max_part[u]=max(max_part[u],sizx[v]);
    }
    max_part[u]=max(max_part[u],n-sizx[u]);//换根法
    ans=min(max_part[u],ans);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        cnt=0;
        ans=0x3f3f3f3f3f;
        scanf("%d",&n);
        memset(sizx,0,sizeof(sizx));
        memset(head,-1,sizeof(head));
        memset(max_part,0,sizeof(max_part));
        memset(tr,0,sizeof(tr));
        for(int i=1; i<n; i++)
        {
            int u,v;
            scanf("%d %d",&u,&v);
            add(u,v);
            add(v,u);
        }
        dfs(1,0);
        int root,minx=0x3f3f3f3f;
        for(int i=1; i<=n; i++)
        {
            if(max_part[i]==ans)
            {
                root=i;
                break;
            }
        }
        cout<<root<<' '<<ans<<endl;
    }
}
发布了205 篇原创文章 · 获赞 12 · 访问量 8506

猜你喜欢

转载自blog.csdn.net/yangzijiangac/article/details/103897318