zoukankan      html  css  js  c++  java
  • uva12489 Combating cancer(树同构)

    转载请注明出处: http://www.cnblogs.com/fraud/           ——by fraud

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3933

    给你两棵无根树,让你判断这两棵树是否同构

    不会判断树同构,果断抄了个模板,乱搞给过掉了。

    首先由于给的是无根树,而要判断无根树是否同构得以重心为根,然后做一个括号序列的哈希。

    于是我们需要先找出重心,要找树的重心得先知道直径。

    找出直径,直径上的点的个数是偶数,那么重心是中间的两个点,如果是奇数个,那么重心是中间那个。

    或者说是根据拓排,每次度数为1的点入队,留下的最后一批就是。

    然而我当时脑抽了一下,求好直径,后用第二种再去搞。。。其实求直径的时候保存一下路径就好了。

    最后,如果有两个重心就做两次哈希,得到两个哈希值,一个就一次。

    最后把两棵树的哈希值比一下是否有相同的。

    /**
     * code generated by JHelper
     * More info: https://github.com/AlexeyDmitriev/JHelper
     * @author xyiyy @https://github.com/xyiyy
     */
    
    #include <iostream>
    #include <fstream>
    
    //#####################
    //Author:fraud
    //Blog: http://www.cnblogs.com/fraud/
    //#####################
    //#pragma comment(linker, "/STACK:102400000,102400000")
    #include <iostream>
    #include <sstream>
    #include <ios>
    #include <iomanip>
    #include <functional>
    #include <algorithm>
    #include <vector>
    #include <string>
    #include <list>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <set>
    #include <map>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <climits>
    #include <cctype>
    
    using namespace std;
    #define pb(X) push_back(X)
    #define rep(X, N) for(int X=0;X<N;X++)
    #define ALL(X) (X).begin(),(X).end()
    typedef unsigned long long ull;
    
    const int maxNode = 10010;
    const int maxEdge = (maxNode << 1);
    //
    // Created by xyiyy on 2015/8/14.
    //
    
    #ifndef ICPC_HASHTREE_HPP
    #define ICPC_HASHTREE_HPP
    
    //树的同构,返回哈希值
    //输入有根树的根,或者无根树的重心
    typedef unsigned long long ull;
    const ull MAGIC = 321;
    
    //
    // Created by xyfra_000 on 2015/8/14.
    //
    
    #ifndef ICPC_ADJLIST_ARRAY_HPP
    #define ICPC_ADJLIST_ARRAY_HPP
    
    #define Foredge(A, X) for(int A = From[X];A!=-1;A = Next[A])
    
    int From[maxEdge], To[maxEdge];
    int Next[maxEdge];
    int Edgecnt;
    
    void init(int n) {
        rep(i, n + 1)From[i] = -1;
        Edgecnt = 0;
    }
    
    void addedge(int u, int v) {
        To[Edgecnt] = v;
        Next[Edgecnt] = From[u];
        From[u] = Edgecnt++;
    }
    
    #endif //ICPC_ADJLIST_ARRAY_HPP
    
    
    ull powMod(ull a, int n) {
        ull ret = 1ULL;
        while (n) {
            if (n & 1)ret *= a;
            a *= a;
            n >>= 1;
        }
        return ret;
    }
    
    struct Hash {
        int length;
        ull value;
    
        Hash() : length(0), value(0) { }
    
        Hash(char c) : length(1), value(c) { }
    
        Hash(int l, int v) : length(l), value(v) { }
    };
    
    bool operator<(const Hash &a, const Hash &b) {
        return a.value < b.value;
    }
    
    Hash operator+(const Hash &a, const Hash &b) {
        return Hash(a.length + b.length, a.value * powMod(MAGIC, b.length) + b.value);
    }
    
    void operator+=(Hash &a, Hash &b) {
        a = a + b;
    }
    
    vector<Hash> childs[maxNode];
    
    Hash dfs(int pre, int cur) {
        Hash ret;
        childs[cur].clear();
        for (int iter = From[cur]; iter != -1; iter = Next[iter]) {
            if (To[iter] != pre) {
                childs[cur].pb(dfs(cur, To[iter]));
            }
        }
        sort(ALL(childs[cur]));
        for (vector<Hash>::iterator iter = childs[cur].begin(); iter != childs[cur].end(); iter++) {
            ret += *iter;
        }
        Hash retL = Hash('(');
        ret = '(' + ret + ')';
        return ret;
    }
    
    ull getHash(int root) {
        return dfs(-1, root).value;
    }
    
    #endif //ICPC_HASHTREE_HPP
    
    //
    // Created by xyfra_000 on 2015/8/14.
    //
    
    #ifndef ICPC_TREEDIAMETER_HPP
    #define ICPC_TREEDIAMETER_HPP
    
    //求树的直径
    //可以通过修改dfs部分变成求带权的树的直径
    
    vector<int> dist;
    
    void dfs(int p, int u, int d) {
        dist[u] = d;
        Foredge(i, u) {
            if (To[i] != p) {
                dfs(u, To[i], d + 1);
            }
        }
    }
    
    int getDiameter(int n) {
        dist.resize(n);
        dfs(-1, 0, 0);
        int u = max_element(ALL(dist)) - dist.begin();
        dfs(-1, u, 0);
        return *max_element(ALL(dist));
    }
    
    
    #endif //ICPC_TREEDIAMETER_HPP
    
    int deg[maxNode];
    int vis[maxNode];
    
    class TaskH {
    public:
        void solve(std::istream &in, std::ostream &out) {
            int n;
            while (in >> n) {
                vector<ull> ans[2];
                rep(times, 2) {
                    int u, v;
                    init(n);
                    rep(i, n + 1)deg[i] = 0;
                    rep(i, n + 1)vis[i] = 0;
                    queue<int> q;
                    rep(i, n - 1) {
                        in >> u >> v;
                        u--, v--;
                        deg[u]++;
                        deg[v]++;
                        addedge(u, v);
                        addedge(v, u);
                    }
                    int dia = getDiameter(n);
                    int num = n;
                    rep(i, n) {
                        if (deg[i] == 1) {
                            q.push(i);
                        }
                    }
                    int gao = 1;
                    if (dia & 1)gao++;
                    while (num > gao && !q.empty()) {
                        u = q.front();
                        q.pop();
                        vis[u] = 1;
                        num--;
                        deg[u]--;
                        for (int i = From[u]; i != -1; i = Next[i]) {
                            int v = To[i];
                            if (!vis[v]) {
                                deg[v]--;
                                if (deg[v] == 1) {
                                    q.push(v);
                                }
                            }
                        }
                    }
                    rep(i, n) {
                        if (!vis[i]) {
                            ans[times].pb(getHash(i));
                        }
                    }
                }
                bool ok = 0;
                rep(i, ans[0].size()) {
                    rep(j, ans[1].size()) {
                        if (ans[0][i] == ans[1][j])ok = 1;
                    }
                }
                if (ok)out << "S" << endl;
                else out << "N" << endl;
            }
        }
    };
    
    int main() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        TaskH solver;
        std::istream &in(std::cin);
        std::ostream &out(std::cout);
        solver.solve(in, out);
        return 0;
    }
  • 相关阅读:
    位运算技巧2
    如果函数的参数是一个指针,不要指望用该指针去申请动态内存
    位运算 技巧1
    野指针?空指针?
    面试题:位操作实现四则运算
    面试题:递归颠倒栈 与栈排序
    求一个数任意位的值及位数
    基数排序
    面试题:最长回文子串(即求对称字符串的最大长度 )
    数据结构之后缀数组suffix array
  • 原文地址:https://www.cnblogs.com/fraud/p/4731174.html
Copyright © 2011-2022 走看看