POJ1655 Balancing Act 求树的重心

题目链接:http://poj.org/problem?id=1655


题目大意:树的重心:找到一个点作为新的树根,其所有的子树中最大子树的节点数最少,那么这个点就是这个树的重心。树的重心的意义在于,删去重心后,生成的多棵树尽可能平衡。


分析:一次搜索即可。DFS每一个点s,找出其各个子树的节点数,纪录最大值son[s],然后比较balance=max(son[s],n-son[s]-1)即为最终结果。


实现代码如下(vector容器纪录边==>125MS):

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int M=20005;
vector <int> adj[M];
int n; //节点数
int son[M]; //该节点的儿子节点数
bool vis[M];
int ans,asize;
void dfs(int s)
{
    vis[s]=1;
    son[s]=0;
    int balance=0;
    int len=adj[s].size();
    for(int j=0;j<len;j++)
    {
        int u=adj[s][j];
        if(vis[u]) continue;
        dfs(u);
        son[s]+=son[u]+1;
        balance=max(balance,son[u]+1);
    }
    balance=max(balance,n-son[s]-1);
    if(balance<asize||(balance==asize&&s<ans))
    {
        ans=s;
        asize=balance;
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) adj[i].clear();
        for(int i=1;i<=n-1;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            adj[u].push_back(v);
            adj[v].push_back(u);
        }
        memset(vis,0,sizeof(vis));
        asize=M;
        dfs(1);
        printf("%d %d\n",ans,asize);
    }
    return 0;
}



前向星纪录边-实现代码如下==>47MS(可见前向星要比vector省去很多时间):

#include <stdio.h>  
#include <string.h>  
#include <iostream>  
#include <algorithm>  
using namespace std;  
const int maxn=20005;  
  
struct note  
{  
    int v,next;  
}edge[maxn*2];  
  
int head[maxn],ip;  
int maxx,point,n,num[maxn];  
  
void init()  
{  
    memset(head,-1,sizeof(head));  
    ip=0;  
}  
  
void addedge(int u,int v)  
{  
    edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++;  
}  
  
void dfs(int u,int pre)  
{  
    int tmp=-0x3f3f3f3f;  
    num[u]=1;  
    for(int i=head[u];i!=-1;i=edge[i].next)  
    {  
        int v=edge[i].v;  
        if(v==pre)continue;  
        dfs(v,u);  
        num[u]+=num[v];  
        tmp=max(tmp,num[v]);  
    }  
    tmp=max(tmp,n-num[u]);///除去以u为根节点的子树部分剩下的节点数  
    if(tmp<maxx||tmp==maxx&&u<point)  
    {  
        point=u;  
        maxx=tmp;  
    }  
}  
  
int main()  
{  
    int T;  
    scanf("%d",&T);  
    while(T--)  
    {  
        scanf("%d",&n);  
        init();  
        for(int i=1;i<n;i++)  
        {  
            int u,v;  
            scanf("%d%d",&u,&v);  
            addedge(u,v);  
            addedge(v,u);  
        }  
        memset(num,0,sizeof(num));  
        maxx=0x3f3f3f3f;  
        dfs(1,-1);  
        printf("%d %d\n",point,maxx);  
    }  
    return 0;  
}  


你可能感兴趣的:(POJ1655 Balancing Act 求树的重心)