Isomorphism of [bzoj 4337] tree

Posted by o3d on Tue, 05 May 2020 20:46:29 +0200

Portal~

Solutions to problems

Tree isomorphism template problem.
Double hash is used for insurance.
The extremely violent method is chosen to deal with the case of two barycenters: for each barycenter, the hash value is calculated separately and then the max value is taken.
When hashing, the first mock exam is done to hash the values of all child nodes, then look at the mood of the child, and multiply the module of the module one by one. Finally, the hash value of the root node is used as the hash value of the whole tree.
code:

#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;
}