首页 > 其他 > 详细

BZOJ4337 : BJOI2015 树的同构

时间:2015-11-21 07:01:30      阅读:360      评论:0      收藏:0      [点我收藏+]

对于一棵无根树,它的重心个数不超过2。

枚举每个重心,以重心为根求出这棵有根树的最小表示,然后取字典序最大的即可。

对于有根树的最小表示,可以看成括号序列,每次把子树的括号序列按字典序排序后依次串连起来即可。

 

#include<cstdio>
#include<string>
#include<algorithm>
#define N 55
using namespace std;
int T,n,i,j,k,x,g[N],v[N<<1],nxt[N<<1],ed,f[N],son[N],mx;string h[N],q[N],val[N];
inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
void findroot(int x,int y){
  son[x]=1;f[x]=0;
  for(int i=g[x];i;i=nxt[i])if(v[i]!=y){
    findroot(v[i],x);
    son[x]+=son[v[i]];
    if(son[v[i]]>f[x])f[x]=son[v[i]];
  }
  if(n-son[x]>f[x])f[x]=n-son[x];
  if(f[x]>mx)mx=f[x];
}
void dfs(int x,int y){
  h[x]="(";
  for(int i=g[x];i;i=nxt[i])if(v[i]!=y)dfs(v[i],x);
  int t=0;
  for(int i=g[x];i;i=nxt[i])if(v[i]!=y)q[t++]=h[v[i]];
  if(t>1)std::sort(q,q+t);
  for(int i=0;i<t;i++)h[x]+=q[i];
  h[x]+=")";
}
string solve(){
  int i;string t="";
  scanf("%d",&n);
  for(ed=mx=0,i=1;i<=n;i++)g[i]=0;
  for(i=1;i<=n;i++){
    scanf("%d",&x);
    if(x)add(i,x),add(x,i);
  }
  findroot(1,0);
  for(i=1;i<=n;i++)if(f[i]==mx){
    dfs(i,0);
    if(h[i]>t)t=h[i];
  }
  return t;
}
int main(){
  scanf("%d",&T);
  for(i=1;i<=T;i++)val[i]=solve();
  for(i=1;i<=T;printf("%d\n",k),i++)for(j=k=i;j;j--)if(val[j]==val[i])k=j;
  return 0;
}

  

BZOJ4337 : BJOI2015 树的同构

原文:http://www.cnblogs.com/clrs97/p/4982839.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!