zoukankan      html  css  js  c++  java
  • Subway (树中心 + 树hash)

    首先找到树的中心或者中心,我这里是找中心,因为我们需要找一个相同的起点,然后最多2个中心就是树的宽度为偶数时,奇数时为1个。

    找到之后需要对树进行hash,使得每个点都具备独特性,使之树的形态能够保证唯一,然后利用hash值,对树的每个节点下的节点进行排序,之后如果判定这两个树是一样的话,我只需要对树进行一次深搜并把遍历的顺序存进数组。然后直接按照数组中的值输出原来映射的字符串就好了。

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    
    const int mod = 1e9 + 7;
    const int maxn = 1e5 + 12345;
    const int seed = 17;
    char inp[16], onp[16];
    
    struct Tree{
        map<string, int>id;
        vector<int>edge[maxn];
        string anw[maxn], rip[maxn];
        int _cnt, ctr[2], siz[maxn], dep[maxn], fa[maxn];
        LL Har[maxn];
        
        ///将遍历顺序存进去
        void done(int st, int fa){
            if(fa == 0) _cnt = 0;
            anw[_cnt ++] = rip[st];
            for(auto x : edge[st]){
                if(x == fa) continue;
                done(x, st);
            }
        }
    
        ///hash技术
        LL dfsh(int st, int fa){
            Har[st] = seed;siz[st] = 1;
            for(auto x : edge[st]){
                if(x == fa) continue;
                dfsh(x, st);
                siz[st] += siz[x];
            }
            sort(edge[st].begin(), edge[st].end(),
                [&](int x, int y){return Har[x] < Har[y];});
            for(auto x : edge[st]){
                if(x == fa) continue;
                Har[st] = (((Har[st] * Har[x]) % mod) ^ Har[x])% mod;
            }
            Har[st] = (Har[st] + siz[st]) % mod;
            Har[st] = (Har[st] * Har[st]) % mod;
            return Har[st];
        }
    
        ///得到深度值
        void getdep(int st, int Fa, int Dep){
            dep[st] = Dep;fa[st] = Fa;
            for(auto x : edge[st]){
                if(x == fa[st]) continue;
                getdep(x,st,Dep + 1);
            }
        }
    
        ///获取中点
        void getCtr(int n){
            getdep(1, 0, 0);
            ctr[0] = max_element(dep + 1, dep + 1 + n) - dep;
            getdep(ctr[0], 0, 0);
            ctr[0] = max_element(dep + 1, dep + 1 + n) - dep;
            int fdep = dep[ctr[0]];
            for(int i = 0; i < fdep/2; i ++)
                ctr[0] = fa[ctr[0]];
            ctr[1] = ctr[0];
            if(fdep & 1) ctr[1] = fa[ctr[1]];
        }
    
        ///重置数据
        void init(int n){
            for(int i = 0; i <= n; i ++)
                edge[i].clear();
            id.clear();_cnt = 1;
        }
    
        ///映射连接的符号,并存进对应的map值为下标的地方
        int toid(string v){
            if(id.find(v) != id.end()) return id[v];
            rip[_cnt] = v;
            return id[v] = _cnt ++;
        }
    
        ///建图,映射值
        void input(int n){
            init(n);int l,r;
            for(int i = 1; i < n; i ++){
                scanf("%s %s", inp, onp);
                l = toid(inp); r = toid(onp);
                edge[l].push_back(r);
                edge[r].push_back(l);
            }
        }
    }X, Y;
    
    void solve(){
        for(int i = 0; i < 2; i ++)
        for(int j = 0; j < 2; j ++)
        if(X.dfsh(X.ctr[i], 0) == Y.dfsh(Y.ctr[j], 0)){
            X.done(X.ctr[i], 0);
            Y.done(Y.ctr[j], 0);
            return;
        }
    }
    
    int main(){
        int n;while(~scanf("%d", &n)){
            X.input(n);
            Y.input(n);
            X.getCtr(n);
            Y.getCtr(n);
            solve();
            for(int i = 0; i < n; i ++)
                printf("%s %s
    ",X.anw[i].c_str(), Y.anw[i].c_str());
        }return 0;
    }

    这次的代码可以说是照搬过来的,菜鸡的自己。

    more crazy more get!
  • 相关阅读:
    Entity SQL 初入
    ObjectQuery查询及方法
    Entity Framework 的事务 DbTransaction
    Construct Binary Tree from Preorder and Inorder Traversal
    Reverse Linked List
    Best Time to Buy and Sell Stock
    Remove Duplicates from Sorted Array II
    Reverse Integer
    Implement Stack using Queues
    C++中const限定符的应用
  • 原文地址:https://www.cnblogs.com/wethura/p/9739059.html
Copyright © 2011-2022 走看看