题面:
树是一种很常见的数据结构。
我们把N个点,N−1条边的连通无向图称为树。
若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树。
对于两个树T1和T2,如果能够把树T1的所有点重新标号,使得树T1和树T2完全相同,那么这两个树是同构的。也就是说,它们具有相同的形态。
现在,给你M个有根树,请你把它们按同构关系分成若干个等价类。
无根树Hash。。。
以树的每一个节点为根,求出Hash值后,存入一个数组里,排序。
比对就像这样
for(int j=1;j<=i;j++){ bool flag=0; for(int k=1;k<=n;k++) if(H[i][k]!=H[j][k]) flag=1; if(!flag) {printf("%d ",j);break;} }
至于怎样求以一个节点为根时树的Hash值,
先把它的子节点的Hash值存入一个vector里,排序,然后就像字符串Hash一样,求就完事了,叶子节点返回 1 。
ll dfs(int x,int fa){ ll res=1;vector<ll> v; for(int i=Head[x];i;i=nex[i]){ int y=ver[i];if(y==fa) continue; v.push_back(dfs(y,x)); } sort(v.begin(),v.end()); for(unsigned int i=0;i<v.size();i++) res=(res*P+v[i])%mod; return res%mod; }
然后就能切掉了啦。
一开始我找树的重心,然后像上面那样求以重心为根节点的Hash值,由于可能有2个重心,取较小值即可。然而只有30pts。QAQ。。。。。。