码迷,mamicode.com
首页 > 其他好文 > 详细

树hash

时间:2020-06-05 20:51:17      阅读:67      评论:0      收藏:0      [点我收藏+]

标签:www   技术   print   std   its   图片   pac   png   namespace   

神仙的博客(我就是用的这种方法)

树hash的方法很多,我用的是上面博客里面的方法

最近跟Wendigo神仙做题目,发现自己思维不行

题目

BJOI2015树的同构

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int mod=998244341;
const int N=100000;
const int M=1299720;
struct edge
{
	int to,nxt;
}e[N*2];
int h[N],E=0;
ll f[N+5],g[N+5],siz[N];
int p[N+5],tot=0;
bitset<M+5> used;
vector<int> hs[N];
int n,m;
int vis[N];
void addedge(int u,int v)
{
	E++;
	e[E].to=v,e[E].nxt=h[u];
	h[u]=E;
	return;
}
void getsieve(int n)
{
	used[0]=used[1]=1;
	tot=0;
	for(int i=2;i<=n;i++)
	{
		if(!used[i]) p[++tot]=i;
		for(int j=1;j<=tot&&p[j]*i<=n;j++)
		{
			used[p[j]*i]=1;
			if(i%p[j]==0) break;
		}
	}
	return;
}
void dfs(int u,int fa)
{
	f[u]=1;
	siz[u]=1;
	for(int i=h[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v==fa) continue;
		dfs(v,u);
		siz[u]+=siz[v];
		f[u]+=f[v]*p[siz[v]]%mod;
		f[u]%=mod;
	}
	return;
}
void dfs1(int u,int fa)
{
	g[u]=0;
	if(u!=1)
	{
		g[u]=(f[fa]-p[siz[u]]*f[u]%mod+mod)%mod;
		g[u]=(g[u]+g[fa]*p[n-siz[fa]]%mod)%mod;		
	}
	for(int i=h[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v==fa) continue;
		dfs1(v,u);
	}
	return;
}
int cmp(vector<int> &a,vector<int> &b)
{
	int la=a.size(),lb=b.size();
	if(la!=lb) return 0;
	for(int i=0;i<la;i++) if(a[i]!=b[i]) return 0;
	return 1;
}
void insert(int tot)
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) h[i]=0;
	E=0;
	int fa;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&fa);
		if(!fa) continue;
		addedge(i,fa);
		addedge(fa,i);
	}
	dfs(1,0);
	dfs1(1,0);
	for(int i=1;i<=n;i++) hs[tot].push_back((g[i]*p[n-siz[i]]%mod+f[i])%mod);
	sort(hs[tot].begin(),hs[tot].end());
	return;
}
int main()
{
	getsieve(M);
	scanf("%d",&m);
	for(int i=1;i<=m;i++) insert(i);
	for(int i=1;i<=m;i++) vis[i]=i; 
	for(int i=1;i<=m;i++)	
	{
		for(int j=i+1;j<=m;j++)
		{
			if(cmp(hs[i],hs[j]))
			{
				vis[j]=min(vis[j],i);
			}
		}
	}
	for(int i=1;i<=m;i++) printf("%d\n",vis[i]);
	return 0;
}

[JSOI2016]独特的树叶

枚举那个树叶,然后在父亲的hash值减2,然后在map里面找

附一张图

技术图片

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int mod=999999137;
const int N=100000;
const int M=1299720;
struct edge
{
	int to,nxt;
}e[N*2+5];
int h[N+5],E=0;
ll f[N+5],g[N+5],t[N+5],siz[N+5];
int p[N+5],tot=0;
bitset<M+5> used;
map<int,int> c;
int n,deg[N+5],pa[N+5];
int root=0;
void addedge(int u,int v)
{
	E++;
	e[E].to=v,e[E].nxt=h[u];
	h[u]=E;
	return;
}
void getsieve(int n)
{
	used[0]=used[1]=1;
	tot=0;
	for(int i=2;i<=n;i++)
	{
		if(!used[i]) p[++tot]=i;
		for(int j=1;j<=tot&&p[j]*i<=n;j++)
		{
			used[p[j]*i]=1;
			if(i%p[j]==0) break;
		}
	}
	return;
}
void dfs(int u,int fa)
{
	f[u]=1;
	siz[u]=1;
	pa[u]=fa;
	for(int i=h[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v==fa) continue;
		dfs(v,u);
		siz[u]+=siz[v];
		f[u]+=f[v]*p[siz[v]]%mod;
		f[u]%=mod;
	}
	return;
}
void dfs1(int u,int fa)
{
	g[u]=0;
	if(u!=root)
	{
		g[u]=(f[fa]-p[siz[u]]*f[u]%mod+mod)%mod;
		g[u]=(g[u]+g[fa]*p[n-siz[fa]]%mod)%mod;		
	}
	for(int i=h[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v==fa) continue;
		dfs1(v,u);
	}
	return;
}
int main()
{
	getsieve(M);
	scanf("%d",&n);
	int u,v;
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&u,&v);
		addedge(u,v);
		addedge(v,u);
	}
	root=1;
	dfs(root,0);
	dfs1(root,0);
	for(int i=1;i<=n;i++) 
	{
		c[(f[i]+g[i]*p[n-siz[i]]%mod)%mod]++;
	}
	n++;
	for(int i=1;i<=n;i++) h[i]=0;
	E=0;
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&u,&v);
		deg[u]++,deg[v]++;
		addedge(u,v);
		addedge(v,u);
	}
	for(int i=1;i<=n;i++) if(deg[i]>1) root=i;
	dfs(root,0);
	dfs1(root,0);
	for(int i=1;i<=n;i++) t[i]=(f[i]+g[i]*p[n-siz[i]]%mod)%mod;
	for(int i=1;i<=n;i++)
	{
		if(deg[i]>1) continue;
		ll has=(t[pa[i]]-2+mod)%mod;
		if(c[has]) return printf("%d\n",i),0;
	}
	return 0;
}

树hash

标签:www   技术   print   std   its   图片   pac   png   namespace   

原文地址:https://www.cnblogs.com/SegmentTree/p/13051673.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!