树同构/树哈希

Posted hesorchen

tags:

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

题目

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

树的同构与哈希

判断两棵树是否同构,可以用树哈希实现,两颗树的哈希值一样时,我们可以判定他们同构。树的哈希只在有根树中有意义。当要判定两棵树是否同构时,我们可以选择它们的重心为根进行哈希。时间复杂度为 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]=xsonyval[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]=xsonyval[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;
}

以上是关于树同构/树哈希的主要内容,如果未能解决你的问题,请参考以下文章

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

[树哈希] 树的同构

哈希算法在判定树同构方面的应用(下)

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

树哈希 学习笔记

树哈希