解题思路
树同构模板题。
为了保险用了双哈希。
选了极其暴力的方法处理两个重心的情况:对于每个重心分别求哈希值然后取max。
哈希的时候,每次将所有子节点的哈希值排好序拿出来,然后看心情瞎搞,随便乘一乘模一模,最后将根节点的哈希值作为整棵树的哈希值。
代码:
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdio>
#include<cstdlib>
using namespace std;
struct tree{
int hed[55],nex[105],lb[105];
int w1[55][55],w2[55][55];
int h1[55],h2[55],ha1,ha2;
int u[5],n,root,tot,lo;
void add(int x,int y){
lo++;
nex[lo]=hed[x];
hed[x]=lo;
lb[lo]=y;
}
void read(){
int x;
memset(hed,0,sizeof(hed));
ha1=ha2=tot=lo=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&x);
if(!x) root=i;
else {add(x,i);add(i,x);}
}
}
int getu(int x,int fa){
int siz=1,flag=0;
for(int i=hed[x];i!=0;i=nex[i])
if(lb[i]!=fa){
int r0=getu(lb[i],x);
if(r0*2>n) flag=1;
siz+=r0;
}
if((n-siz)*2>n) flag=1;
if(!flag) u[++tot]=x;
return siz;
}
void ha(int x,int fa){
h1[x]=17;h2[x]=59;
int len=0;
for(int i=hed[x];i!=0;i=nex[i])
if(lb[i]!=fa){
ha(lb[i],x);len++;
w1[x][len]=h1[lb[i]];
w2[x][len]=h2[lb[i]];
}
if(!len) return ;
sort(w1[x]+1,w1[x]+len+1);
sort(w2[x]+1,w2[x]+len+1);
for(int i=1;i<=len;i++) h1[x]=(h1[x]*19260%817+w1[x][i]*17%233)%1777;
for(int i=1;i<=len;i++) h2[x]=(h2[x]*83374%294+w2[x][i]*40%332)%1443;
}
void solve(){
read();
int r=getu(root,root);
for(int i=1;i<=tot;i++){
ha(u[i],u[i]);
ha1=max(ha1,h1[u[i]]);
ha2=max(ha2,h2[u[i]]);
}
}
bool operator == (const tree p) const{
return (ha1==p.ha1 && ha2==p.ha2);
}
}T[55];
int m;
int main(){
scanf("%d",&m);
for(int i=1;i<=m;i++) T[i].solve();
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
if(T[i]==T[j]) {printf("%d\n",j);break;}
return 0;
}