首页 > 代码库 > POJ 1655 Balancing Act(求树的重心)

POJ 1655 Balancing Act(求树的重心)

题目大意:

就是要求树的重心,重心的定义就是删除这个点使得森林尽量平衡。

也可以让分治子树的时候使得每颗子树的数量在nlogn以内。


思路分析:

son [x] 表示x的子树的数量  不包括自己。

balance 表示最大的森林的节点数。

最后我们要让最大的balance 最小。

balance = max (balance ,n - 1 - son[x]  , son[j] +1)..


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define maxn 20005
#define inf 0x3f3f3f3f
using namespace std;

int tot;
int to[maxn<<1];
int next[maxn<<1];
int head[maxn];
int son[maxn];
int n;
void init()
{
    tot=0;
    memset(head,0,sizeof head);
}
void addedge(int u,int v)
{
    tot++;
    next[tot]=head[u];
    to[tot]=v;
    head[u]=tot;
}
bool vis[maxn];
int ans,ansize;
void dfs(int now)//求树的重心
{
    son[now]=0;
    int balance=0;
    for(int p = head[now] ; p ;p = next[p])
    {
        int v = to[p];
        if(vis[v])continue;
        vis[v]=true;
        dfs(v);
        son[now]+=son[v]+1;
        balance=max(balance,son[v]+1);
    }
    balance=max(balance,n-1-son[now]);
    if(balance<ansize || balance==ansize && now<ans)
    {
        ans=now,ansize=balance;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%d",&n);
        for(int i=2;i<=n;i++)
        {
            int s,e;
            scanf("%d%d",&s,&e);
            addedge(s,e);
            addedge(e,s);
        }
        memset(vis,false,sizeof vis);
        ansize=inf;
        vis[1]=true;
        dfs(1);
        printf("%d %d\n",ans,ansize);
    }
    return 0;
}


POJ 1655 Balancing Act(求树的重心)