题面传送门
首先把这颗树转化成最小的括号序。
然后有一个神奇的结论:如果两棵有根树的最小括号序相同,那么他们同构。
仔细想想其实是这么回事,这个东西使树的形态确定。
然后对于无根树我们找到它的重心做根就好了
时间复杂度\(O(mn^2)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 100
#define K 150
#define mod 10007
#define eps (1e-9)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
using namespace std;
int n,m,k,T,root,Gh,siz[N+5],x,Maxn[N+5],ToT;string Ans[N+5],F[N+5],G[N+5];
struct yyy{int to,z;};
struct ljb{int head,h[N+5];yyy f[N+5];I void add(int x,int y){f[++head]=(yyy){y,h[x]};h[x]=head;}}s;
I void dfs1(int x,int last){siz[x]=1;Maxn[x]=0;yyy tmp;for(int i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&(dfs1(tmp.to,x),siz[x]+=siz[tmp.to],Maxn[x]=max(siz[tmp.to],Maxn[x]));}
I void dfs2(int x,int last){
int i;yyy tmp;for(i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&(dfs2(tmp.to,x),0);Gh=0;for(i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&(G[++Gh]=F[tmp.to],0);sort(G+1,G+Gh+1);F[x].clear();for(i=1;i<=Gh;i++) F[x]+='0'+G[i]+'1';
}
int main(){
freopen("1.in","r",stdin);
re int i,j;scanf("%d",&T);for(i=1;i<=T;i++){
scanf("%d",&n);s.head=0;Me(s.h,0);for(j=1;j<=n;j++) scanf("%d",&x),x?(s.add(x,j),s.add(j,x),0):(root=j);dfs1(root,0);for(j=1;j<=n;j++) Ans[i]+="11";
for(j=1;j<=n;j++) Maxn[j]=max(Maxn[j],n-siz[j]),Maxn[j]<=n/2&&(dfs2(j,0),Ans[i]=min(Ans[i],F[j]),0);for(j=1;j<=i;j++)if(Ans[j]==Ans[i]){printf("%d\n",j);break;}
}
}