![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
题目描述 树是一种很常见的数据结构。 我们把N个点,N-1条边的连通无向图称为树。 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树。 对于两个树T1和T2,如果能够把树T1的所有点重新标号,使得树T1和树T2完全相 同,那么这两个树是同构的。也就是说,它们具有相同的形态。 现在,给你M个有根树,请你把它们按同构关系分成若干个等价类。 输入格式 第一行,一个整数M。 接下来M行,每行包含若干个整数,表示一个树。第一个整数N表示点数。接下来N 个整数,依次表示编号为1到N的每个点的父亲结点的编号。根节点父亲结点编号为0。 输出格式 输出M行,每行一个整数,表示与每个树同构的树的最小编号。 样例一 input 4 4 0 1 1 2 4 2 0 2 3 4 0 1 1 1 4 0 1 2 3 output 1 1 3 1 样例解释 编号为1, 2, 4 的树是同构的。编号为3 的树只与它自身同构。 限制与约定 对于100%的数据,1≤N,M≤501≤N,M≤50 时间限制:1s1s 空间限制:256MB
这道题是树hs裸题,树hs的思路就是,先把每个节点的点权赋为1,然后父节点累加子节点平方和自己的值向上返回,
就是一个递归的过程,然后自然溢出
但是每个树的根节点可能会不同,所以我们要有对于每个树选根的唯一标准
对,就是树重心,一个树可能有多个重心,那么我们只需要一个超级原点就ok 了
最后比较超级原点的hs值,就能知道是否同构
有一点玄学的地方,就是用seed的方式过不了,也不知道是为什么
1 #include<bits/stdc++.h> 2 #define N 100 3 #define clear(a,val) memset(a,val,sizeof(a)) 4 using namespace std; 5 typedef unsigned long long ult; 6 int n,m,f,cnt=1,pp; 7 int head[N],nxt[N*2],to[N*2],size[N],ans[N]; 8 ult vv[N],val[N]; 9 inline void add(int u,int v) 10 {nxt[cnt]=head[u],to[cnt]=v,head[u]=cnt++;} 11 inline void cl(){ 12 clear(size,0),clear(ans,0),clear(head,-1),cnt=1,pp=0; 13 } 14 int dfs(int now,int fa) 15 { 16 size[now]=1;int ma=-1; 17 for(int i=head[now];i!=-1;i=nxt[i]) 18 { 19 int t=to[i]; 20 if(t==fa)continue; 21 size[now]+=dfs(t,now); 22 ma=max(ma,size[t]); 23 } 24 ma=max(ma,n-size[now]); 25 if(ma<=(n>>1))ans[++pp]=now; 26 return size[now]; 27 } 28 inline void weigh() 29 { 30 dfs(1,-1); 31 for(int i=1;i<=pp;i++) 32 add(n+1,ans[i]); 33 } 34 ult cal(int now,int fa) 35 { 36 vv[now]=1; 37 for(int i=head[now];i!=-1;i=nxt[i]) 38 { 39 int t=to[i]; 40 if(t==fa)continue; 41 vv[now]+=cal(t,now); 42 } 43 return vv[now]*vv[now]; 44 } 45 inline void init_build_weigh_solve() 46 { 47 clear(head,-1); 48 scanf("%d",&m); 49 for(int i=1;i<=m;i++) 50 { 51 cl(); 52 scanf("%d",&n); 53 for(int j=1;j<=n;j++) 54 { 55 scanf("%d",&f); 56 if(f==0)continue; 57 else add(f,j),add(j,f); 58 } 59 weigh(); 60 val[i]=cal(n+1,-1); 61 } 62 for(int i=1;i<=m;i++) 63 { 64 for(int j=1;j<=i;j++) 65 { 66 if(val[i]==val[j]) 67 { 68 printf("%d\n",j); 69 break; 70 } 71 } 72 } 73 } 74 int main() 75 { 76 init_build_weigh_solve(); 77 return 0; 78 }