P5043 模板树同构([BJOI2015]树的同构) |树哈希

Posted naruto-mzx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P5043 模板树同构([BJOI2015]树的同构) |树哈希相关的知识,希望对你有一定的参考价值。

题目描述

树是一种很常见的数据结构。

我们把 (N) 个点,(N-1) 条边的连通无向图称为树。

若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树。

对于两个树 (T_1)(T_2),如果能够把树 (T_1)? 的所有点重新标号,使得树 (T_1)? 和树 (T_2) 完全相同,那么这两个树是同构的。也就是说,它们具有相同的形态。

现在,给你 (M) 个有根树,请你把它们按同构关系分成若干个等价类。

输入格式

第一行,一个整数 (M)

接下来 (M) 行,每行包含若干个整数,表示一个树。第一个整数 (N)表示点数。接下来 (N) 个整数,依次表示编号为 (1)(N) 的每个点的父亲结点的编号。根节点父亲结点编号为 (0)

输出格式

输出 (M) 行,每行一个整数,表示与每个树同构的树的最小编号。


好东西,好东西

#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
inline int read(){
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if(ch==‘-‘)f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-48;ch=getchar();}
    return x*f;
}
const int N=60,M=2*N,mod=998244353;
int nxt[M],head[N],go[M],tot;
inline void add(int u,int v){
	nxt[++tot]=head[u],head[u]=tot,go[tot]=v;
}
int p[1000010],top,siz[N],h[N],g[N],fr[N],turn;
bool vis[1000010];
vector<int>v[N];
inline void getp(int n){
	for(int i=2;i<=n;i++){
		if(!vis[i])p[++top]=i;
		for(int j=1;j<=top&&i*p[j]<=n;j++){
			vis[i*p[j]]=1;
			if(i%p[j]==0)break;
		}
	}
}
int n;
void DFS_1(int x,int fa){
	h[x]=siz[x]=1;
	for(int i=head[x];i;i=nxt[i]){
		int v=go[i];
		if(v==fa)continue;
		DFS_1(v,x);
		h[x]=(h[x]+h[v]*p[siz[v]]%mod)%mod;
		siz[x]+=siz[v];
	}
}
void DFS_2(int x,int fa,int V){
	g[x]=(h[x]+V*p[n-siz[x]]%mod)%mod;
	v[turn].push_back(g[x]);
	V=(V*p[n-siz[x]]%mod+1)%mod;
	for(int i=head[x];i;i=nxt[i]){
		int v=go[i];
		if(v==fa)continue;
		DFS_2(v,x,(V+h[x]-1-h[v]*p[siz[v]]%mod+mod)%mod);
	}
}
inline bool equal(int a,int b){
	int len=v[a].size();
	if(len!=v[b].size())return 0;
	for(int i=0;i<len;i++)if(v[a][i]!=v[b][i])return 0;
	return 1;
}
signed main(){
	getp(1000009);
	int m; cin>>m;
	for(turn=1;turn<=m;turn++){
		n=read(); tot=0;
		memset(head,0,sizeof(head));
		memset(nxt,0,sizeof(nxt));
		for(int i=1,x;i<=n;i++){
			x=read();
			if(x==0)continue;
			add(i,x),add(x,i);
		}
		DFS_1(1,0);
		DFS_2(1,0,0);
		sort(v[turn].begin(),v[turn].end());
	}
	for(int i=1;i<=m;i++)fr[i]=i;
	for(int i=2;i<=m;i++)
	for(int j=1;j<i;j++){
		if(equal(i,j)){
			fr[i]=fr[j];
			break;
		}
	}
	for(int i=1;i<=m;i++)
	printf("%d
",fr[i]);
}

以上是关于P5043 模板树同构([BJOI2015]树的同构) |树哈希的主要内容,如果未能解决你的问题,请参考以下文章

luogu P5043 模板树同构([BJOI2015]树的同构)

树同构/树哈希

4337. [BJOI2015]树的同构树哈希

[BJOI2015]树的同构

树hs[BJOI2015]树的同构

bzoj 4337[BJOI2015]树的同构 - 括号序列