版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/86668373
题目
题解
这道题让我们把树的结构归类,自然而然就想到了哈希,我们对这整颗树哈希一遍,然后判同构就只需要找哈希值一样的树就可以了。
综上所述,这是一道树上哈希模板题。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1e3+10;
template<typename T>inline void read(T &x)
{
T s=0,f=1; static char ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (!isdigit(ch)) { f=-1; ch=getchar(); }
while (isdigit(ch)) s=(s<<1)+(s<<3)+(ch^48), ch=getchar();
x=s*f;
}
ll ans[maxn][maxn],head[maxn],ver[maxn],Next[maxn],tot;
inline void add(int x,int y)
{
ver[++tot]=y,Next[tot]=head[x],head[x]=tot;
}
inline ll Hash(int x,int f)//树哈希
{
ll q[maxn],ans=maxn,top=0;
for (int i=head[x];i;i=Next[i])//遍历所以子节点
if (ver[i]!=f)//不能再次遍历以遍历的点,即x的父亲
q[++top]=Hash(ver[i],x);
sort(q+1,q+top+1);//把哈希打得更乱
for (int i=1;i<=top;++i)//对x点计算哈希值
ans=ans*2333+q[i];
return ans*2333+maxn+1;
}
int main()
{
static int m;read(m);
for(int i=1;i<=m;++i)
{
tot=0;
memset(head,0,sizeof(head));
static int n;read(n);
for (int j=1;j<=n;++j)
{
static int x;read(x);
if (x)
add(x,j),add(j,x);
}
for (int j=1;j<=n;++j)
ans[i][j]=Hash(j,0);//树哈希
sort(ans[i]+1,ans[i]+n+1);
for (int j=1,k=0;j<=i;++j)
{
while (k<=n)
if (ans[i][++k]!=ans[j][k]) break;//找同构
if (k>n)
{
printf("%d\n",j);
break;
}//找到同构就输出
}
}
return 0;
}