对两棵树都进行树哈希,求出以每个节点为根的哈希值
然后将第一棵树的哈希值都插入一个set,枚举第二棵树里的叶子节点,考虑删去它后它的父亲节点的哈希值是否在set里即可。
哈希方法是
\(f[u] = 1 + \sum \limits_{v \in \text{son}{u}}prime[size_v] * f[v]\)
dfs两遍就行
#include
const int MOD = 1e9 + 7;
const int MX = 2e6 + 7;
int prime[MX / 10], prin;
void init() {
static bool vis[MX];
for (int i = 2; i < MX; i++) {
if (!vis[i]) prime[++prin] = i;
for (int j = 1; j <= prin && i * prime[j] < MX; j++) {
vis[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
}
const int N = 1e5 + 7;
void M(int &x) {
(((x >= MOD) && (x -= MOD)) || ((x < 0) && (x += MOD)));
}
struct Tree {
int cnt, head[N], n, sz[N], dp[N], g[N];
struct E {
int v, ne;
} e[N << 1];
void init(int _n) {
n = _n;
cnt = 1;
}
void add(int u, int v) {
e[++cnt].v = v; e[cnt].ne = head[u]; head[u] = cnt;
}
void dfs1(int u, int f) {
sz[u] = 1;
dp[u] = 1;
for (int i = head[u], v; i; i = e[i].ne) {
v = e[i].v;
if (v == f) continue;
dfs1(v, u);
M(dp[u] += 1LL * dp[v] * prime[sz[v]] % MOD);
sz[u] += sz[v];
}
}
void dfs2(int u, int f, int V) {
M(g[u] = dp[u] + 1LL * V * prime[n - sz[u]] % MOD);
for (int i = head[u], v; i; i = e[i].ne) {
v = e[i].v;
if (v == f) continue;
dfs2(v, u, (g[u] - 1LL * prime[sz[v]] * dp[v] % MOD + MOD) % MOD);
}
}
} tree1, tree2;
int n, deg[N], adj[N];
std::set st;
int main() {
init();
scanf("%d", &n);
tree1.init(n); tree2.init(n + 1);
for (int i = 1; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
tree1.add(u, v);
tree1.add(v, u);
}
for (int i = 1; i <= n; i++) {
int u, v;
scanf("%d%d", &u, &v);
tree2.add(u, v);
tree2.add(v, u);
deg[u]++; deg[v]++;
adj[u] = v; adj[v] = u;
}
tree1.dfs1(1, 0); tree1.dfs2(1, 0, 0);
tree2.dfs1(1, 0); tree2.dfs2(1, 0, 0);
for (int i = 1; i <= n; i++)
st.insert(tree1.g[i]);
int ans = 0;
for (int i = 1; i <= n + 1; i++) {
if (deg[i] == 1) {
int fa = adj[i];
int V; M(V = tree2.g[fa] - 2 + MOD);
if (st.find(V) != st.end()) {
ans = i;
break;
}
}
}
printf("%d\n", ans);
return 0;
}