【模板】树哈希

    科技2026-02-05  4

    OI Wiki - 树哈希


    板子

    #include <bits/stdc++.h> using namespace std; typedef unsigned long long ull; typedef long long ll; const int INF = 0x3f3f3f3f; const ll inf = (1ll << 60); const int N = 1e6 + 10; vector<int> e[N]; int n, m; namespace treeHash { int primes[N], cnt; // 存储所有质数 bool st[N]; // 存储每个数是否已被筛掉 void get_primes(int n) { for (int i = 2; i <= n; i++) { if (!st[i]) primes[++cnt] = i; for (int j = 1; primes[j] <= n / i; j++) { st[primes[j] * i] = true; if (i % primes[j] == 0) break; } } } int Mx[N], sz[N], root; void calcSize(int u, int fa) { sz[u] = 1, Mx[u] = 0; for (int i = 0, lim = e[u].size(); i < lim; i++) { int v = e[u][i]; if (v != fa && v) { calcSize(v, u); Mx[u] = max(Mx[u], sz[v]); sz[u] += sz[v]; } } Mx[u] = max(Mx[u], n - sz[u]); if (Mx[u] < Mx[root]) { root = u; } } ull Hash[N]; ull getTreeHash(int u, int fa) { sz[u] = 1; ull res = 1; for (int i = 0, lim = e[u].size(); i < lim; i++) { int v = e[u][i]; if (v != fa && v) { res += getTreeHash(v, u) * primes[sz[v]]; sz[u] += sz[v]; } } return res; } } using namespace treeHash; int main() { ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); get_primes(100000); cin >> m; // m棵树 for (int i = 1; i <= m; i++) { cin >> n; // 每棵树有n个节点 给出树的结构 父节点为0的是根节点 for (int v = 1, u; v <= n; v++) { cin >> u; e[u].push_back(v); e[v].push_back(u); } Mx[root = 0] = INF; calcSize(1, 0); // 求树的重心 一棵树最多只会有两个重心 Hash[i] = inf;// hash值初始化 选个较大值 for (int j = 1; j <= n; j++) { if (Mx[j] == Mx[root]) {// 找重心 Hash[i] = min(Hash[i], getTreeHash(j, 0)); } } for (int j = 1; j <= i; j++) { if (Hash[i] == Hash[j]) { cout << j << endl; break; } } for (int j = 0; j <= n; j++) { e[j].clear(); } } return 0; }
    Processed: 0.013, SQL: 9