树哈希学习笔记
1. 作用
判断一些树是否同构。
2. 方法
2.1. 具体操作
这类方法需要一个多重集的哈希函数。以某个结点为根的子树的哈希值,就是以它的所有儿子为根的子树的哈希值构成的多重集的哈希值,即:
其中
以代码中运用的哈希方法为例,式子是:
其中,g(i)表示整数到整数的映射,说人话就是一种运算,将一个整数转化为另一个整数
2.2. 代码
#include<bits/stdc++.h>
#define ull unsigned long long
using namespace std;
int n,head[1000005],edgenum;
struct edge{
int to,nxt;
}e[2000005];
void add_edge(int u,int v)
{
e[++edgenum].nxt=head[u];
e[edgenum].to=v;
head[u]=edgenum;
}
ull mask;
ull get_hash(ull x)
{
x^=mask;
x^=x<<13;
x^=x>>7;
x^=x<<17;
x^=mask;
return x;
}
ull h[1000005];
set<ull> tr;
void dfs(int u,int fa)
{
h[u]=1;
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa) continue;
dfs(v,u);
h[u]+=get_hash(h[v]);
}
tr.insert(h[u]);
}
int main()
{
srand((unsigned)time(0));
mask=1ll*rand()*rand();
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs(1,0);
printf("%d",tr.size());
return 0;
}
2.3. 正确性证明
每次前后各异或一次mask,其实相当于一种加密和解密的过程,第一次是解密,第二次是加密
每一次get_hash运算,都是对解密后的数字进行处理,所以最后的得数都是与mask进行一次异或运算的结果
因为求解方法是相加,所以若两棵树同构,经过运算后数的和必然相同
分类:
学习笔记 / 图论
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律