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