Title Description
Trees are a very common data structure.
We call a connected undirected graph with N points and N-1 edges a tree.
If a point is taken as a root and traversed from the root, the other points have a precursor, and the tree becomes a rooted tree.
For two trees T1T_1T1 and T2T_2T2, if all points of the tree T1T_1T1 can be re-labeled so that the tree T1T_1T1 and the tree T2T_2T2 are identical, then the two trees are isomorphic. That is to say, they have the same shape.
Now, give you M rooted trees. Please divide them into several equivalent classes according to their isomorphism.
Input format
The first line, an integer M.
Next, M lines, each containing several integers, represent a tree. The first integer N represents points. Next, N integers, in turn, represent the number of the father node of each point numbered 1 to N. The father node number of the root node is 0.
Output format
Output M lines, an integer per line, representing the smallest number of trees isomorphic to each tree.
Input and Output Samples
Input #1
4
4 0 1 1 2
4 2 0 2 3
4 0 1 1 1
4 0 1 2 3
Output #1
1
1
3
1
Note/hint
Trees numbered 1, 2, 4 are isomorphic. A tree numbered 3 is isomorphic only to itself.
In 100% of the data, 1 < N,M < 501 Leq N,M Leq 501 N and M < 50.
#include<stdio.h> struct node{ int ch[2]; int size; int val; }; node nn[4096]; int num; void add(char* s,int n,int now){ nn[now].size++; if(n==0){ nn[now].val++; return; } if(!nn[now].ch[s[0]-'0']){ num++; nn[num].ch[0]=0; nn[num].ch[1]=0; nn[num].size=0; nn[num].val=0; nn[now].ch[s[0]-'0']=num; } add(s+1,n-1,nn[now].ch[s[0]-'0']); } int query(char* s,int n,int now,int i){ if(n==0){ if(nn[now].val==0) nn[now].val=i; return nn[now].val; } if(!nn[now].ch[s[0]-'0']){ num++; nn[num].ch[0]=0; nn[num].ch[1]=0; nn[num].size=0; nn[num].val=0; nn[now].ch[s[0]-'0']=num; } return query(s+1,n-1,nn[now].ch[s[0]-'0'],i); } void sol(char* s,int n){ if(n==0) return; int lastwz=0; int cnt=0; for(int i=0;i<n;i++){ if(s[i]=='0') cnt++; else cnt--; if(cnt==0){ sol(s+lastwz+1,i-lastwz-1); lastwz=i+1; } } num=0; nn[num].ch[0]=0; nn[num].ch[1]=0; nn[num].size=0; nn[num].val=0; cnt=0; lastwz=0; for(int i=0;i<n;i++){ if(s[i]=='0') cnt++; else cnt--; if(cnt==0){ add(s+lastwz,i-lastwz+1,0); lastwz=i+1; } } int now=0; cnt=0; while(1){ if(nn[now].size==0) break; nn[now].size--; if(nn[now].val){ nn[now].val--; now=0; continue; } if(nn[now].ch[0]&&nn[nn[now].ch[0]].size){ s[cnt]='0'; now=nn[now].ch[0]; } else{ s[cnt]='1'; now=nn[now].ch[1]; } cnt++; } } char s[64][128]; int len[64]; int head[64],last[128],to[128],cnt=0; int size[64]; void add(int u,int v){ cnt++; last[cnt]=head[u]; head[u]=cnt; to[cnt]=v; } void dfs(int u,int f){ size[u]=1; for(int i=head[u];i;i=last[i]){ int v=to[i]; if(v==f) continue; dfs(v,u); size[u]+=size[v]; } } int findroot(int u,int f,int n){ for(int i=head[u];i;i=last[i]){ int v=to[i]; if(v==f) continue; if(size[v]<=n) continue; return findroot(v,u,n); } return u; } int tim; void dfs2(int u,int f,int id){ s[id][tim]='0'; tim++; for(int i=head[u];i;i=last[i]){ int v=to[i]; if(v==f) continue; dfs2(v,u,id); } s[id][tim]='1'; tim++; } int main(){ int m; scanf("%d",&m); for(int i=1;i<=m;i++){ int n; scanf("%d",&n); for(int j=1;j<=n;j++) head[j]=0; cnt=0; for(int j=1;j<=n;j++){ int v; scanf("%d",&v); if(v){ add(j,v); add(v,j); } } dfs(1,0); int u=findroot(1,0,n>>1); int v=0; for(int j=head[u];j;j=last[j]){ if((size[to[j]]<<1)==n){ v=to[j]; break; } } tim=0; dfs2(u,v,i); if(v) dfs2(v,u,i); sol(s[i],tim); len[i]=tim; } num=0; nn[num].ch[0]=0; nn[num].ch[1]=0; nn[num].size=0; nn[num].val=0; for(int i=1;i<=m;i++) printf("%d\n",query(s[i],len[i],0,i)); return 0; }