BZOJ 4337 树的同构 发表于 2017-03-28 | 更新于 2018-06-18 LinkSolution树的哈希什么的感觉还是很有意思呢 数据太小估计怎么搞搞都能过。。 另外有一个惊人的事实是一个树至多有222个重心。画个图似乎确实是的样子。。 Code1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798#include "lucida"using std::map;using std::sort;using std::pair;typedef unsigned long long qword;const int MAXN=60,INF=0x1f1f1f1f;qword p3[MAXN];struct _{_() { p3[0]=1; for(int i=1;i<MAXN;++i) { p3[i]=p3[i-1]*3; }}}Auto;struct Edge { int to;Edge *pre; Edge(int to,Edge *pre):to(to),pre(pre) {} void *operator new(size_t) { static Edge *Me=alloc(Edge,MAXN*MAXN<<1); return Me++; }};struct Tree { int n;Edge *G[MAXN]; void Adde(int f,int t) { G[f]=new Edge(t,G[f]); G[t]=new Edge(f,G[t]); } void operator () (int f,int t) { Adde(f,t); } int sz[MAXN],f[MAXN]; void preDFS(int pos,int from) { sz[pos]=1; for(Edge *e=G[pos];e;e=e->pre) { if(e->to!=from) { int u=e->to; preDFS(u,pos); chkmx(f[pos],sz[u]); sz[pos]+=sz[u]; } } chkmx(f[pos],n-sz[pos]); } pair<qword,int> Pool[MAXN][MAXN]; qword DFS(int pos,int from) { pair<qword,int> *sh=Pool[pos];qword hash=1; int sc=0;sz[pos]=1; for(Edge *e=G[pos];e;e=e->pre) { if(e->to!=from) { int u=e->to; sh[++sc]=pair<qword,int>(DFS(u,pos),sz[u]); sz[pos]+=sz[u]; } } sort(sh+1,sh+1+sc); for(int i=1;i<=sc;++i) { (hash*=p3[sh[i].second+1])+=sh[i].first; } (hash*=3)+=2; return hash; } qword Hash() { preDFS(1,0); static int gc[MAXN],gcc; f[gc[gcc=0]=0]=INF; for(int i=1;i<=n;++i) { if(f[i]<f[gc[1]]) { gc[gcc=1]=i; } else if(f[i]==f[gc[1]]) { gc[++gcc]=i; } } assert(gcc<=2); qword res=0; for(int i=1;i<=gcc;++i) { chkmx(res,DFS(gc[i],0)); } return res; }}tr[MAXN];int main() { freopen("input","r",stdin); map<qword,int> record; int m;is>>m; for(int i=1;i<=m;++i) { is>>tr[i].n; for(int j=1;j<=tr[i].n;++j) { int fa;is>>fa; if(fa) tr[i](fa,j); } qword hash=tr[i].Hash(); if(!record.count(hash)) { record[hash]=i; } os<<record[hash]<<'\n'; } return 0;}