zoukankan      html  css  js  c++  java
  • Luogu 5043 【模板】树同构([BJOI2015]树的同构)

    BZOJ 4337

    简单记录一种树哈希的方法:以$x$为根的子树的哈希值为$sum_{y in son(x)}f_y*base_i$,$f_y$表示以$y$为根的树的哈希值,其中$i$表示$f_y$在若干个儿子中的排名,$base$是$rand$出的对一个质数取模之后的很大的数。

    对于本题这样的情况,可以每一个结点都拿出来作为根计算一下,然后再把所有的结果排个序,如果两棵树同构那么排序之后得到的序列一定是一样的。

    时间复杂度$O(n^3)$。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <vector>
    using namespace std;
    typedef long long ll;
    
    const int N = 55;
    const ll P = 1e9 + 7;
    
    int n[N], m, tot, head[N];
    ll base[N], h[N][N], f[N];
    vector <ll> g[N];
    
    struct Edge {
        int to, nxt;
    } e[N << 1];
    
    inline void add(int from, int to) {
        e[++tot].to = to;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    inline void read(int &X) {
        X = 0; char ch = 0; int op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    void dfs(int x, int fat) {
        g[x].clear();
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(y == fat) continue;
            dfs(y, x);
            g[x].push_back(f[y]);
        }
    
        if(g[x].empty()) {
            f[x] = 1LL;
            return;
        }
    
        f[x] = 0LL;
        sort(g[x].begin(), g[x].end());
        int vecSiz = g[x].size();
        for(int i = 0; i < vecSiz; i++) 
            (f[x] += g[x][i] * base[i + 1] % P) %= P;
    }
    
    inline bool chk(int x, int y) {
        for(int i = 1; i <= n[x]; i++)
            if(h[x][i] != h[y][i]) return 0;
        return 1;
    }
    
    int main() {
        srand(19260817);
        for(int i = 1; i <= 50; i++)
            base[i] = rand() * rand() % P * rand() % P * rand() % P * rand() % P;
    
        read(m);
        for(int i = 1; i <= m; i++) {
            tot = 0;
            memset(head, 0, sizeof(head));
    
            read(n[i]);
            for(int fa, j = 1; j <= n[i]; j++) {
                read(fa);
                if(fa) add(j, fa), add(fa, j);
            }
    
            for(int j = 1; j <= n[i]; j++) {
                dfs(j, 0);
                h[i][j] = f[j];
            }
            sort(h[i] + 1, h[i] + n[i] + 1);
        }
    
        for(int i = 1; i <= m; i++) {
            for(int j = 1; j <= i; j++) {
                if(n[i] != n[j]) continue;
                if(chk(i, j)) {
                    printf("%d
    ", j);
                    break;
                }
            }
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    进程与线程
    the art of seo(chapter seven)
    the art of seo(chapter six)
    the art of seo(chapter five)
    the art of seo(chapter four)
    the art of seo(chapter three)
    the art of seo(chapter two)
    the art of seo(chapter one)
    Sentinel Cluster流程分析
    Sentinel Core流程分析
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/10050318.html
Copyright © 2011-2022 走看看