Description

nodgd家里种了一棵树,有一天nodgd比较无聊,就把这棵树画在了一张纸上。另一天nodgd更无聊,就又画了一张。
这时nodgd发现,两次画的顺序是不一样的,这就导致了原本的某一个节点u0在第一幅图中编号为u1,在第二副图中编号为u2。
于是,nodgd决定检查一下他画出的两棵树到底是不是一样的。nodgd已经给每棵树的节点都从1到n进行了编号,即每棵树n个节点。
如果存在一个1到n的排列p1p2…pn,对于第一幅图中的任意一条边(u,v),在第二幅图中都能找到一条边(pu,pv),则认为这两幅图中的树是一样的。

知道是树hash,但是从来没写过这个玩意儿,没有信心写出来,然后想了个水法只捞到10分。。
其实是树hash的模板题。。无根树转有根树是经典操作了,把重心当根,超过1个重心就直接新建一个点做为根,注意要把重心拉上去,重心之间的边显然不能走。然后处理完两棵树以后直接树hash,具体的话就是:

(((hash[x]*=base)^=tmp[i])+=tmp[i])^=tmp[i];

从下往上hash就可以了,注意base不能太小,最好不要模,冲突可能性比较大,还是自然溢出比较好,。
然后方案的话扫一遍用hash来映射就ok了。
一个小错误导致WA半天。。

#include<cstdio>
#include<algorithm>
#include<cstring>
#define mp make_pair
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
int n,m;
const int N=4e5+5;
typedef long long ll;
const ll base=1e9+7;
int root,root1,root2;
int tot,head[N],f[N],size[N],ans[N],next[N],go[N],del[N];
ll hash[N],tmp[N];
pair<ll,int>q1[N],q2[N];
int read()
{int x=0,f=1;char ch=getchar();while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}inline void add(int x,int y)
{go[++tot]=y;next[tot]=head[x];head[x]=tot;go[++tot]=x;next[tot]=head[y];head[y]=tot;
}
inline void getroot(int x,int fa)
{size[x]=1;for(int i=head[x];i;i=next[i]){int v=go[i];if (v==fa||del[i])continue;getroot(v,x);size[x]+=size[v];f[x]=max(f[x],size[v]);}f[x]=max(f[x],n-size[x]);if (!root||f[x]<f[root])root=x;
}
inline int gethash(int x,int fa)
{for(int i=head[x];i;i=next[i]){int v=go[i];if (v==fa||del[i])continue;gethash(v,x);}int cnt=0;for(int i=head[x];i;i=next[i]){int v=go[i];if (v!=fa&&!del[i])tmp[++cnt]=hash[v];}sort(tmp+1,tmp+cnt+1);hash[x]=base;fo(i,1,cnt)(((hash[x]*=base)^=tmp[i])+=tmp[i])^=tmp[i];
}
inline void solve1()
{fo(i,1,n-1){int x,y;x=read(),y=read();add(x,y);}root=0;int r1=0,r2=0;getroot(1,0);fo(i,1,n)if (f[i]==f[root])r2=r1,r1=i;if (r2){for(int i=2;i<=tot;i+=2){int v=go[i];if (go[i]==r1&&go[i^1]==r2||go[i]==r2&&go[i^1]==r1){del[i]=del[i^1]=1;break;}}add(n*2+1,r1);add(n*2+1,r2);root=n*2+1;}root1=root;gethash(root,0);
}
inline void solve2()
{fo(i,1,n-1){int x,y;x=read(),y=read();add(x+n,y+n);}root=0;int r1=0,r2=0;getroot(n+1,0);fo(i,n+1,n+n)if (f[i]==f[root])r2=r1,r1=i;if (r2){for(int i=2;i<=tot;i+=2){int v=go[i];if (go[i]==r1&&go[i^1]==r2||go[i]==r2&&go[i^1]==r1){del[i]=del[i^1]=1;break;}   }add(n*2+2,r1);add(n*2+2,r2);root=n*2+2;}root2=root;gethash(root,0);
}
inline void getans(int x1,int x2,int fa1,int fa2)
{int tot1=0,tot2=0;for(int i=head[x1];i;i=next[i]){int v=go[i];if (v!=fa1&&!del[i])q1[++tot1]=mp(hash[v],v);}for(int i=head[x2];i;i=next[i]){int v=go[i];if (v!=fa2&&!del[i])q2[++tot2]=mp(hash[v],v);}sort(q1+1,q1+1+tot1);sort(q2+1,q2+1+tot2);fo(i,1,tot1)ans[q1[i].second]=q2[i].second;for(int i=head[x1];i;i=next[i]){int v=go[i];if (v!=fa1&&!del[i])getans(v,ans[v],x1,x2);}
}
int main()
{freopen("check.in","r",stdin);freopen("check.out","w",stdout);scanf("%d",&n);tot=1;solve1();solve2();if (hash[root1]!=hash[root2]){printf("NO\n");return 0;}ans[root1]=root2;getans(root1,root2,0,0);printf("YES\n");fo(i,1,n)printf("%d ",ans[i]-n);return 0;
}

JZOJ5454. 【NOIP2017提高A组冲刺11.5】仔细的检查 树hash相关推荐

  1. Jzoj5454【NOIP2017提高A组冲刺11.5】仔细的检查

    nodgd家里种了一棵树,有一天nodgd比较无聊,就把这棵树画在了一张纸上.另一天nodgd更无聊,就又画了一张. 这时nodgd发现,两次画的顺序是不一样的,这就导致了原本的某一个节点u0在第一幅 ...

  2. JZOJ5454. 【NOIP2017提高A组冲刺11.5】仔细的检查

    题目 Sample Input 输入1: 3 1 2 2 3 1 3 3 2 输入2: 4 1 2 2 3 3 4 1 2 1 3 1 4 Sample Output 输出1: YES 1 3 2 输 ...

  3. JZOJ 5441. 【NOIP2017提高A组冲刺11.1】序列

    Description 给定一个1~n的排列x,每次你可以将x1~xi翻转.你需要求出将序列变为升序的最小操作次数.有多组数据. Input 第一行一个整数t表示数据组数. 每组数据第一行一个整数n, ...

  4. jzoj_5455. 【NOIP2017提高A组冲刺11.6】拆网线

    Description 企鹅国的网吧们之间由网线互相连接,形成一棵树的结构.现在由于冬天到了,供暖部门缺少燃料,于是他们决定去拆一些网线来做燃料.但是现在有K只企鹅要上网和别人联机游戏,所以他们需要把 ...

  5. [JZOJ5459]【NOIP2017提高A组冲刺11.7】密室

    Description 小X 正困在一个密室里,他希望尽快逃出密室. 密室中有N 个房间,初始时,小X 在1 号房间,而出口在N 号房间. 密室的每一个房间中可能有着一些钥匙和一些传送门,一个传送门会 ...

  6. JZOJ 5458. 【NOIP2017提高A组冲刺11.7】质数

    Description 小X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感.小X 认为,质数是一切自然数起源的地方. 在小X 的认知里,质数是除了本身和1 以外,没有其他因数的数 ...

  7. JZOJ 5455. 【NOIP2017提高A组冲刺11.6】拆网线

    Description 企鹅国的网吧们之间由网线互相连接,形成一棵树的结构.现在由于冬天到了,供暖部门缺少燃料,于是他们决定去拆一些网线来做燃料.但是现在有K只企鹅要上网和别人联机游戏,所以他们需要把 ...

  8. JZOJ 5445. 【NOIP2017提高A组冲刺11.2】失格

    Description 胆小鬼连幸福都会害怕,碰到棉花都会受伤,有时还被幸福所伤. --太宰治<人间失格> 回顾我的一生,一共有n个事件,每一个事件有一个幸福值p_i. 我想用n-1条线把 ...

  9. JZOJ5445. 【NOIP2017提高A组冲刺11.2】失格

    Description 胆小鬼连幸福都会害怕,碰到棉花都会受伤,有时还被幸福所伤. --太宰治<人间失格> 回顾我的一生,一共有n个事件,每一个事件有一个幸福值p_i. 我想用n-1条线把 ...

最新文章

  1. 解题报告:P5960 【模板】差分约束算法(及常用技巧)
  2. 什么是RSS订阅 Really Simple Syndication(聚合)
  3. hibernate 一对多_java面试题之Hibernate
  4. 学习鸟哥的Linux私房菜笔记(2)——基础指令
  5. linux中gid和groups区别,linux用户与组管理
  6. Silverlight使用DataGrid的模板列(DataGridTemplateColumn)实现类似TreeListView控件的效果
  7. php在线编辑器fckeditor,[原创]继续给力:PHP中使用FckEditor在线编辑器详解
  8. CentOS下DB2数据库安装过程详解
  9. Unix/Linux Command Reference
  10. 16进制发送 mqtt客户端调试工具_MQTT客户端调试工具(MQTT Simulate Device)
  11. Android代码中实现关机
  12. linux 磁盘配额 期限,linux磁盘配额管理
  13. CentOS7安装PHP5.3.28
  14. Java基础面试题(史上最全基础面试题,精心整理100家互联网企业面经)
  15. gitbook踩坑指南-无法转pdf、epub等;pdf调字体大小
  16. 备战三个月,2021年阿里+腾讯+快手offer都已拿到!详解系列文章
  17. 机器学习复习:线性回归1
  18. 人脸识别登录:加强系统认证
  19. 6.824:FaRM笔记
  20. Java学习笔记----File类与IO流

热门文章

  1. 模型的偏差与方差的理解
  2. P352作业10-P360复习
  3. 关于PDR和P2DR两个网络安全模型
  4. 特征值与奇异值的对比及应用
  5. Shaders for Game
  6. 终于做了这个决定, 准备认认真真的学习java啦,
  7. Airsim接口文档
  8. 哈工大C语言程序设计精髓第三周
  9. mac常用快捷键,Mac文件重命名快捷键,Mac OS快速访问系统根目录
  10. ExecuteNonQuery方法和ExecuteScalar方法的区别