树同构/树哈希
Posted hesorchen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树同构/树哈希相关的知识,希望对你有一定的参考价值。
题目
树的同构与哈希
判断两棵树是否同构,可以用树哈希实现,两颗树的哈希值一样时,我们可以判定他们同构。树的哈希只在有根树中有意义。当要判定两棵树是否同构时,我们可以选择它们的重心为根进行哈希。时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)。
关于树哈希,用的比较多的方法是将子树从小到大排序,对于第 i i i个子树,乘上第 i i i个质数。
v a l [ y ] = ∑ x ∈ s o n y v a l [ x ] ∗ p r i m e [ s i z e ( x ) ] val[y]=\\sum_{x\\in {son_y}} val[x]*prime[size(x)] val[y]=x∈sony∑val[x]∗prime[size(x)]
当然,也有很多哈希方法值得尝试,比如字符串哈希中使用较多的进制哈希写法简单,也很不错。
v a l [ y ] = ∑ x ∈ s o n y v a l [ x ] ∗ b a s e c n t [ x ] val[y]=\\sum_{x\\in {son_y}} val[x]*base^{cnt[x]} val[y]=x∈sony∑val[x]∗basecnt[x]
个人比较喜欢的哈希是异或 ,一般瞎hash一下就不会被卡。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 50 + 5;
vector<int> mp[N];
vector<pair<int, int>> centr[N];
int siz[N], mx[N];
int n;
int dfs(int u, int fa)
{
int res = 0;
siz[u] = 0;
for (auto v : mp[u])
{
if (v == fa)
continue;
int val = dfs(v, u);
siz[u] += val;
res = max(res, val);
}
mx[u] = max(res, n - (siz[u] + 1));
return siz[u] + 1;
}
void init()
{
for (int i = 0; i < N; i++)
mp[i].clear(), mx[i] = 0;
}
int Hash(int u, int fa)
{
int sum = 1;
vector<int> res;
for (auto v : mp[u])
{
if (v == fa)
continue;
res.emplace_back(Hash(v, u));
}
sort(res.begin(), res.end());//必须要排序才能保证正确性!
for (auto it : res)
sum += it * 131 ^ 133331;
return sum;
}
int get(int x)
{
init();
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
int fa;
cin >> fa;
if (fa == 0)
continue;
mp[i].emplace_back(fa);
mp[fa].emplace_back(i);
}
dfs(1, -1);
int maxx = 0x3f3f3f3f;
for (int i = 1; i <= n; i++)
maxx = min(maxx, mx[i]);
for (int i = 1; i <= n; i++)
if (maxx == mx[i])
centr[x].emplace_back(make_pair(i, Hash(i, -1)));
for (auto it : centr[x])
for (int j = 1; j <= x; j++)
for (auto it2 : centr[j])
if (it.second == it2.second)
return j;
return -1;
}
int main()
{
int m;
cin >> m;
for (int i = 1; i <= m; i++)
cout << get(i) << endl;
return 0;
}
以上是关于树同构/树哈希的主要内容,如果未能解决你的问题,请参考以下文章