POJ1655 Balancing Act 求树的重心

来源:互联网 发布:mac finder 侧边栏 编辑:程序博客网 时间:2024/04/30 05:03

题目链接: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;  }  


0 0