bzoj4337树的同构

树是一种很常见的数据结构。
我们把N个点,N-1条边的连通无向图称为树。
若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树。
对于两个树T1和T2,如果能够把树T1的所有点重新标号,使得树T1和树T2完全相
同,那么这两个树是同构的。也就是说,它们具有相同的形态。
现在,给你M个有根树,请你把它们按同构关系分成若干个等价类。
树哈希模板题。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 52
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int tt,n,head[N],tot,num[N];
ll disso[N][N],ha[N];
const int base=19260817;
struct node{
    int n,to;
}e[N<<1];
inline void add(int u,int v){
    e[++tot].n=head[u];
    e[tot].to=v;
    head[u]=tot;
}
void dfs(int u,int fa,int deep){
    int ji[N],top=0;
    ji[++top]=deep;
    for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
        int v=e[i].to;
        dfs(v,u,deep+1);
        ji[++top]=ha[v];
    }
    ha[u]=0;
    sort(ji+1,ji+top+1);
    for(int i=1;i<=top;++i)ha[u]=(ha[u]*base+ji[i])%mod;
}
int main(){
    scanf("%d",&tt);
    for(int i=1;i<=tt;++i){
        scanf("%d",&n);num[i]=n;
        memset(head,0,sizeof(head));tot=0;
        int ba;
        for(int j=1;j<=n;++j){
            scanf("%d",&ba);
            if(ba)add(ba,j),add(j,ba);
        }
        for(int j=1;j<=n;++j){
            dfs(j,0,1);disso[i][j]=ha[j];
        }
        sort(disso[i]+1,disso[i]+n+1);
        for(int j=1;j<=i;++j){
            if(num[j]!=num[i])continue;bool tag=0;
            for(int k=1;k<=n;++k)if(disso[i][k]!=disso[j][k])tag=1;
            if(!tag){
                printf("%d\n",j);
                break;
            }
        }
    }
    return 0;
}

 

posted @ 2018-11-02 21:24  comld  阅读(182)  评论(0编辑  收藏  举报