BZOJ 4754: [Jsoi2016]独特的树叶

对两棵树都进行树哈希,求出以每个节点为根的哈希值
然后将第一棵树的哈希值都插入一个set,枚举第二棵树里的叶子节点,考虑删去它后它的父亲节点的哈希值是否在set里即可。
哈希方法是
\(f[u] = 1 + \sum \limits_{v \in \text{son}{u}}prime[size_v] * f[v]\)
dfs两遍就行

#include <bits/stdc++.h>

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<int> 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;
}
posted @ 2020-02-10 22:55  Mrzdtz220  阅读(94)  评论(0)    收藏  举报