树同构笔记

\(\text{Problem}\)

判断两棵无根树是否同构
\(\text{SP7826 TREEISO - Tree Isomorphism}\)

树哈希 \(\text{Code}\)

\(O(n log n)\)

#include <cstdio>
#include <iostream>
#include <tr1/unordered_map>
#define IN inline
using namespace std;

template <typename T>
IN void read(T &x) {
	x = 0; char ch = getchar(); int f = 0;
	for(; !isdigit(ch); f = (ch == '-' ? 1 : f), ch = getchar());
	for(; isdigit(ch); x = (x<<3)+(x<<1)+(ch^48), ch = getchar());
	if (f) x = ~x + 1;
}

typedef long long LL;
const int N = 1e5 + 5, M = 1300000, P = 998244353;
int vis[M], pr[N + 100], tot, n;

IN void Sieve() {
	for(int i = 2; i <= M; i++) {
		if (!vis[i]) pr[++tot] = i;
		for(int j = 1; j <= tot && i * pr[j] <= M; j++) {
			vis[i * pr[j]] = 1;
			if (i % pr[j] == 0) break;
		}
	}
}

struct Tree {
	int h[N], tot, siz[N], f[N], g[N];
	struct edge{int to, nxt;}e[N * 2];
	IN void add(int x, int y) {e[++tot] = edge{y, h[x]}, h[x] = tot;}
	void dfs1(int x, int fa) {
		siz[x] = f[x] = 1;
		for(int i = h[x]; i; i = e[i].nxt) {
			int v = e[i].to;
			if (v == fa) continue;
			dfs1(v, x), siz[x] += siz[v], f[x] = (f[x] + (LL)f[v] * pr[siz[v]] % P) % P;
		}
	}
	void dfs2(int x, int fa) {
		for(int i = h[x]; i; i = e[i].nxt) {
			int v = e[i].to;
			if (v == fa) continue;
			g[v] = (f[v] + (g[x] - (LL)f[v] * pr[siz[v]] % P + P) % P * pr[n - siz[v]] % P) % P;
			dfs2(v, x);
		}
	}
	IN void init() {
		for(int i = 1; i <= n; i++) h[i] = 0;
		tot = 0;
		for(int i = 1, x, y; i < n; i++) read(x), read(y), add(x, y), add(y, x);
		dfs1(1, 0), g[1] = f[1], dfs2(1, 0);
	}
}g1, g2;

tr1::unordered_map <int, int> mp;

int main() {
	Sieve(); int T; read(T);
	for(; T; --T) {
		read(n), g1.init(), g2.init();
		for(int i = 1; i <= n; i++) mp[g1.g[i]] = 1;
		int flag = 1;
		for(int i = 1; i <= n; i++) if (!mp[g2.g[i]]) {flag = 0; break;}
		if (flag) printf("YES\n"); else printf("NO\n");
		for(int i = 1; i <= n; i++) mp[g1.g[i]] = 0;
	}
}
posted @ 2022-09-18 09:06  leiyuanze  阅读(42)  评论(0)    收藏  举报