TREEISO - Tree Isomorphism
如果是有根树,我们只需要从根开始树哈希即可。如果是无根树,一种方案是,依次选取每个点作为根,但复杂度无法接受。当然可以换根 DP,但有一个比较聪明的方法。
找到两棵树的重心进行树哈希。注意重心最多有两个,所以要进行两次树哈希,对哈希值进行对比。
令
通常我们使用 Xor-Hash,代码实现如下:
ull shift(ull x)
{
x ^= P;
x ^= (x << 7);
x ^= (x >> 13);
x ^= (x << 17);
x ^= P;
return x;
}
其中
此外,哈希通常的实现需要取模,不过也可以用无符号整型自然溢出。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <set>
using namespace std;
const int N = 2e5 + 5;
vector<int> G[N], G2[N];
int t, n;
using ull = unsigned long long;
ull Hashing[N];
const ull P = 182930841;
ull shift(ull x)
{
x ^= P;
x ^= (x << 7);
x ^= (x >> 13);
x ^= (x << 17);
x ^= P;
return x;
}
set<int> s1, s2;
int sz[N];
void dfs(int u, int f)
{
sz[u] = 1;
int maxn = 0;
for (int& j : G[u])
{
if (j != f)
{
dfs(j, u);
sz[u] += sz[j];
maxn = max(maxn, sz[j]);
}
}
maxn = max(maxn, n - sz[u]);
if (maxn <= n / 2)
{
s1.insert(u);
}
}
void dfs2(int u, int f)
{
sz[u] = 1;
int maxn = 0;
for (int& j : G2[u])
{
if (j != f)
{
dfs2(j, u);
sz[u] += sz[j];
maxn = max(maxn, sz[j]);
}
}
maxn = max(maxn, n - sz[u]);
if (maxn <= n / 2)
{
s2.insert(u);
}
}
void Tree_Hashing_1(int u, int f)
{
Hashing[u] = 1;
for (int j : G[u])
{
if (j != f)
{
Tree_Hashing_1(j, u);
Hashing[u] += shift(Hashing[j]);
}
}
}
void Tree_Hashing_2(int u, int f)
{
Hashing[u] = 1;
for (int j : G2[u])
{
if (j != f)
{
Tree_Hashing_2(j, u);
Hashing[u] += shift(Hashing[j]);
}
}
}
int main()
{
scanf("%d", &t);
while (t--)
{
s1.clear(), s2.clear();
scanf("%d", &n);
for (int i = 1; i <= n; i++) G[i].clear(), G[i].shrink_to_fit(), G2[i].clear(), G2[i].shrink_to_fit();
for (int i = 1; i < n; i++)
{
int u, v;
scanf("%d%d", &u, &v);
G[u].emplace_back(v);
G[v].emplace_back(u);
}
for (int i = 1; i < n; i++)
{
int u, v;
scanf("%d%d", &u, &v);
G2[u].emplace_back(v);
G2[v].emplace_back(u);
}
dfs(1, 1);
dfs2(1, 1);
set<int> ss;
for (int j : s1) Tree_Hashing_1(j, 0), ss.insert(Hashing[j]);
for (int j : s2)
{
Tree_Hashing_2(j, 0);
if (ss.count(Hashing[j]))
{
printf("YES\n");
goto W;
}
}
printf("NO\n");
W:;
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现