BZOJ4337 [BJOI2015] 树的同构 树上哈希

版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/86668373

题目

BZOJ 4337
luogu 5043

题解

这道题让我们把树的结构归类,自然而然就想到了哈希,我们对这整颗树哈希一遍,然后判同构就只需要找哈希值一样的树就可以了。
综上所述,这是一道树上哈希模板题。

代码

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

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/86668373
今日推荐