判断两棵无根树是否同构只需要把重心提作根哈希即可。由于只添加了一个叶子,重心的位置几乎不发生偏移,所以直接把两棵树的重心提起来,逐层找哈希值不同且对应的两子树即可。被一个普及组子问题卡一年。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define ul unsigned long long
#define N 100010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,ans,f[N],g[N];
struct tree
{
int p[N],t,size[N],root;
ul hax[N],f[N];
struct data{int to,nxt;}edge[N<<];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void dfs(int k,int from)
{
size[k]=;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from)
dfs(edge[i].to,k),size[k]+=size[edge[i].to];
}
int findroot(int k,int s)
{
int mx=;
for (int i=p[k];i;i=edge[i].nxt)
if (size[edge[i].to]<size[k]&&size[edge[i].to]>size[mx]) mx=edge[i].to;
if (size[mx]*>s) return findroot(mx,s);
else return k;
}
void refind()
{
for (int i=p[root];i;i=edge[i].nxt)
if (size[edge[i].to]*>=size[root]) {root=edge[i].to;break;}
}
void gethash(int k,int from)
{
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from) gethash(edge[i].to,k);
int cnt=;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from) f[++cnt]=hax[edge[i].to];
sort(f+,f+cnt+);
hax[k]=;
for (int i=;i<=cnt;i++) hax[k]=hax[k]*+f[i];
hax[k]+=size[k]*;
}
}a,b;
bool cmp(const int&x,const int&y)
{
return a.hax[x]<a.hax[y];
}
bool cmp2(const int&x,const int&y)
{
return b.hax[x]<b.hax[y]||b.hax[x]==b.hax[y]&&x>y;
}
void work(int x,int y)
{
int cnt=,cnt2=;
for (int i=a.p[x];i;i=a.edge[i].nxt)
if (a.size[a.edge[i].to]<a.size[x]) f[++cnt]=a.edge[i].to;
for (int i=b.p[y];i;i=b.edge[i].nxt)
if (b.size[b.edge[i].to]<b.size[y]) g[++cnt2]=b.edge[i].to;
sort(f+,f+cnt+,cmp);
sort(g+,g+cnt2+,cmp2);
if (cnt>cnt2||cnt2>cnt+) return;
if (cnt2==cnt+)
{
int t=;
for (int i=,j=;i<=cnt2;i++,j++)
if (a.hax[f[j]]!=b.hax[g[i]]||j>cnt) if (!t) t=g[i++];else return;
if (t) ans=min(ans,t);
return;
}
if (cnt2==cnt)
{
int u,v;
for (u=;u<=cnt;u++) if (a.hax[f[u]]!=b.hax[g[u]]) break;
if (!u) return;
if (a.hax[f[u]]<b.hax[g[u]]) for (v=u;v<cnt;v++) if (a.hax[f[v+]]!=b.hax[g[v]]) break;
if (!v) return;
for (int i=v+;i<=cnt;i++) if (a.hax[f[i]]!=b.hax[g[i]]) return;
for (int i=;i<=cnt;i++) if (b.hax[g[v]]==b.hax[g[i]]) work(f[u],g[i]);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4754.in","r",stdin);
freopen("bzoj4754.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();ans=n+;
for (int i=;i<n;i++)
{
int x=read(),y=read();
a.addedge(x,y),a.addedge(y,x);
}
for (int i=;i<=n;i++)
{
int x=read(),y=read();
b.addedge(x,y),b.addedge(y,x);
}
a.dfs(,),b.dfs(,);
a.root=a.findroot(,n),b.root=b.findroot(,n+);
a.dfs(a.root,a.root),b.dfs(b.root,b.root);
a.gethash(a.root,a.root),b.gethash(b.root,b.root);
work(a.root,b.root);
if (n&) a.refind();
else b.refind();
a.dfs(a.root,a.root),b.dfs(b.root,b.root);
a.gethash(a.root,a.root),b.gethash(b.root,b.root);
work(a.root,b.root);
cout<<ans;
return ;
}

BZOJ4754 JSOI2016独特的树叶(哈希)的更多相关文章

  1. bzoj4754[JSOI2016]独特的树叶

    这个题....别人写得怎么都....那么短啊? 我怎么....WA了好几次啊....怎么去loj扒了数据才调出来啊? 这个算法...怎么我还是不知道对不对啊 怎么回事啊怎么回事啊怎么回事啊? 请无视上 ...

  2. 【BZOJ4754】独特的树叶(哈希)

    [BZOJ4754]独特的树叶(哈希) 题面 BZOJ 给定一个\(n\)个节点的树A和一个\(n+1\)个节点的树\(B\) 求\(B\)的一个编号最小的节点,使得删去这个节点后\(A,B\)同构 ...

  3. BZOJ 4754 [JSOI2016]独特的树叶 | 树哈希判同构

    题目链接 这道题是一道判断无根树同构的模板题,判断同构主要的思路就是哈希. 一遇到哈希题,一百个人能有一百零一种哈希方式,这篇题解随便选用了一种--类似杨弋<Hash在信息学竞赛中的一类应用&g ...

  4. BZOJ4754 & 洛谷4323 & LOJ2072:[JSOI2016]独特的树叶——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4754 https://www.luogu.org/problemnew/show/P4323 ht ...

  5. P4323 [JSOI2016]独特的树叶(树哈希)

    传送门 树哈希?->这里 反正大概就是乱搞--的吧-- //minamoto #include<bits/stdc++.h> #define R register #define l ...

  6. Luogu 4323 [JSOI2016]独特的树叶

    新技能get 树哈希,考虑到两棵树相同的条件,把每一个结点的哈希值和树的siz写进哈希值里去. 做出A树每一个结点为根时的树的哈希值丢进set中,然后暴力枚举B树中度数为1的点,求出删掉这个点之后的哈 ...

  7. [JSOI2016]独特的树叶

    https://zybuluo.com/ysner/note/1177340 题面 有一颗大小为\(n\)的树\(A\),现加上一个节点并打乱编号,形成树\(B\),询问加上的节点最后编号是多少? \ ...

  8. Luogu P4323 [JSOI2016]独特的树叶

    一道比较好的树Hash的题目,提供一种不一样的Hash方法. 首先无根树的同构判断一般的做法只有树Hash,所以不会的同学可以做了Luogu P5043 [模板]树同构([BJOI2015]树的同构) ...

  9. bzoj 4754: [Jsoi2016]独特的树叶

    不得不说这是神题. %%%   http://blog.csdn.net/samjia2000/article/details/51762811 #include <cstdio> #in ...

随机推荐

  1. 北京Uber优步司机奖励政策(2月20日~2月21日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  2. 成都Uber优步司机奖励政策(2月24日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  3. 《Java I/O 从0到1》 - 第Ⅰ滴血 File

    前言 File 类的介绍主要会依据<Java 编程思想>以及官网API .相信大家在日常工作中,肯定会遇到文件流的读取等操作,但是在搜索过程中,并没有找到一个介绍的很简洁明了的文章.因此, ...

  4. cakephp2.x 多个应用程序公用一个核心类库

    环境Windows,apache,cake版本2.3.3 Cake项目路径 D:\wamp\www\Mycakephp 浏览器打开 http://localhost/Mycakephp 能够正常访问到 ...

  5. 使用GC 初始化DG(将备份集复制到目标端再初始化)

    概述 当前环境中有一个GC节点,一套RAC 11.2.0.4的数据库,一个已经使用GC进行在线初始化好的dg环境,需要模拟在远端使用rman备份集进行初始化DG的操作.   恢复环境 当前环境中 已经 ...

  6. InnoDB锁冲突案例演示

      Preface       As we know,InnoDB is index organized table.InnoDB engine supports row-level lock bas ...

  7. uvaoj 133 - The Dole Queue(逻辑,环形队列数数)

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

  8. JDK11安装后,环境变量的坑

    安装了最新的JDK11,安装完后设置环境变量,打开CMD,没生效 检查了3遍,都没发现问题,在PATH中将JAVA设置移到第一也不行 最后偶然发现,在点击如图右下的‘编辑文本’,用文本方式编辑时,发现 ...

  9. python中为什么 if/while/def/class语句需要冒号?

    python中冒号主要用于增强可读性(ABC语言实验的结果之一).考虑一下这个: if a == b print(a) 与 if a == b: print(a) 注意第二种方法稍微容易一些.请进一步 ...

  10. 测试模拟 白屏 / FOUC

    白屏和FOUC 白屏与无样式内容闪烁(FOUC)是因为不同浏览器加载与显示页面的机制不同而造成的. 我们可以通过一个实验来进行测试和模拟白屏.FOUC的现象,让我们更好的理解白屏.FOUC. 测试de ...