BZOJ4754 JSOI2016独特的树叶(哈希)
判断两棵无根树是否同构只需要把重心提作根哈希即可。由于只添加了一个叶子,重心的位置几乎不发生偏移,所以直接把两棵树的重心提起来,逐层找哈希值不同且对应的两子树即可。被一个普及组子问题卡一年。
#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<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() {int x=0,f=1;char c=getchar();while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),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<<1];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]=1;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=0;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]*2>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]*2>=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=0;for (int i=p[k];i;i=edge[i].nxt)if (edge[i].to!=from) f[++cnt]=hax[edge[i].to];sort(f+1,f+cnt+1);hax[k]=0;for (int i=1;i<=cnt;i++) hax[k]=hax[k]*107+f[i];hax[k]+=size[k]*509;} }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=0,cnt2=0;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+1,f+cnt+1,cmp);sort(g+1,g+cnt2+1,cmp2);if (cnt>cnt2||cnt2>cnt+1) return;if (cnt2==cnt+1){int t=0;for (int i=1,j=1;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=1;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+1]]!=b.hax[g[v]]) break;if (!v) return;for (int i=v+1;i<=cnt;i++) if (a.hax[f[i]]!=b.hax[g[i]]) return;for (int i=1;i<=cnt;i++) if (b.hax[g[v]]==b.hax[g[i]]) work(f[u],g[i]);} } int main() { #ifndef ONLINE_JUDGEfreopen("bzoj4754.in","r",stdin);freopen("bzoj4754.out","w",stdout);const char LL[]="%I64d\n"; #elseconst char LL[]="%lld\n"; #endifn=read();ans=n+1;for (int i=1;i<n;i++){int x=read(),y=read();a.addedge(x,y),a.addedge(y,x);}for (int i=1;i<=n;i++){int x=read(),y=read();b.addedge(x,y),b.addedge(y,x);}a.dfs(1,1),b.dfs(1,1);a.root=a.findroot(1,n),b.root=b.findroot(1,n+1);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&1) 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 0; }
转载于:https://www.cnblogs.com/Gloid/p/9961329.html
BZOJ4754 JSOI2016独特的树叶(哈希)相关推荐
- P5043 【模板】树同构([BJOI2015]树的同构 // P4323 [JSOI2016]独特的树叶
一.P5043 [模板]树同构([BJOI2015]树的同构): #include<iostream> #include<cstdio> #include<algorit ...
- 洛谷 - P4323 [JSOI2016]独特的树叶(树上哈希+换根dp)
题目链接:点击查看 题目大意:给出一棵 n 个节点的树 A ,再给出一棵 n + 1 个节点的树 B,题目保证了树 B 是树 A 添加了一个叶子结点后的一棵树,只不过编号的顺序不同,现在问这个叶子节点 ...
- 【BZOJ - 4754】独特的树叶(树哈希)
题干: JYY有两棵树A和B:树A有N个点,编号为1到N:树B有N+1个点,编号为1到N+1.JYY知道树B恰好是由树A加上一个叶 节点,然后将节点的编号打乱后得到的.他想知道,这个多余的叶子到底是树 ...
- P4323-[JSOI2016]独特的树叶【换根dp,树哈希】
正题 题目链接:https://www.luogu.com.cn/problem/P4323 题目大意 给出nnn个点的树和加上一个点之后的树(编号打乱). 求多出来的是哪个点(如果有多少个就输出编号 ...
- [暑假的bzoj刷水记录]
(这篇我就不信有网站来扣) 这个暑假打算刷刷题啥的 但是写博客好累啊 堆一起算了 隔一段更新一下. 7月27号之前刷的的就不写了 , 写的累 代码不贴了,可以找我要啊.. 2017.8.27upd ...
- 哈希算法在判定树同构方面的应用(下)
哈希算法在判定树同构方面的应用 在上一篇文章中我们介绍了 枚举根节点哈希 和 求重心哈希 两种方法来判断两棵无根树是否同构. 但是如果有些题目中我必须要计算出每个根节点的 fff 值,且 n≤1e5n ...
- 【公告】xx 网络白皮书和Praxxis 技术文件正式发布
2019年12月4日,大开曼岛--David Chaum和Praxxis团队宣布发布xx网络白皮书和Praxxis技术文件.这些文件提供了关于xx网络和xx币的详细信息和见解,这是一种革命性的区块链和 ...
- 怎样设计一个好玩的游戏——游戏设计的艺术
前言: 一个好玩的游戏,就是要让玩家在玩游戏的过程中感到愉快的游戏体验.游戏品质一般可以分为三个层次:普通.精品.经典. 仅仅要游戏能赚钱的好游戏可算是精品游戏,而经典的游戏,必定有深厚的游戏内涵,甚 ...
- OnlyOffice配置文档
OnlyOffice配置参数文档 更多内容可以访问官方文档 https://api.onlyoffice.com/editors/basic 1.基础参数 参数名称 类型 描述 例子 document ...
最新文章
- JavaScript可否多线程? 深入理解JavaScript定时机制
- php项目导入其他包,将一个外部项目导入Thinkphp环境中
- stm32基本入门(一)
- SSD 超详细入门(代码+原文)
- 案例分析|能源行业大数据案例分析
- Grounded video description
- scratch趣味编程——挖矿小游戏
- 项目进度管理方法——里程碑式管理
- 音频处理与压缩技术漫谈
- 物联网应用技术有哪些?
- python为在线漫画站点自制非官方API(未完待续)
- C语言time.h中srand(),rand()等等函数产生随机数的用法。
- 光照与渲染(十)- 自发光材质
- 【微信小程序】WXML模板语法 —— 数据绑定
- Atcode120E 1D Party
- Oracle存储过程中loop、for循环的用法
- 语音特征MFCC和PLP
- Spring MVC源码 ----- @RequestBody和@ResponseBody原理解析
- 【Windows C++】powershell 获取chrome密码并上传
- 预约快递取件接口API对接demo
热门文章
- ThreadLocal是否会引发内存泄露的分析 good
- JAVA中操作符的优先级
- [iOS] 在UIToolBar中增加UILabel等控件(xib/storyboard图形界面方式)
- Eclipse常见问题集锦
- postfix 554-5.7.0 Reject
- java.sql.SQLException: Zero date value prohibited 报错分析
- 2. Oracle 数据库实例启动关闭过程
- JQuery笔记(二)jq常用方法animate()
- 802.15.4的超帧
- Android输入输出机制之来龙去脉