Subway (树中心 + 树hash)
Posted wethura
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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; }
这次的代码可以说是照搬过来的,菜鸡的自己。
以上是关于Subway (树中心 + 树hash)的主要内容,如果未能解决你的问题,请参考以下文章
POJ1635 Subway tree systems ——(判断树的同构,树的最小表示法)
URAL(timus) 1272 Non-Yekaterinburg Subway(最小生成树)