BZOJ 4754: [Jsoi2016]独特的树叶

对两棵树都进行树哈希,求出以每个节点为根的哈希值
然后将第一棵树的哈希值都插入一个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;
}

你可能感兴趣的:(BZOJ 4754: [Jsoi2016]独特的树叶)