HDU5732 Subway【树重心 树哈希】
HDU5732 Subway
题意:
给出两棵大小为\(N\)的同构树,要求输出对应的节点
\(N\le 10^5\)
题解:
由于重心最多只有两个,找到重心之后以重心为根进行树哈希,找到相同哈希值的根之后递归输出即可
输出儿子的时候要先对哈希值排序,保证递归进去的儿子节点也是同构的
这里用的哈希方法是\(f[u] = 1 + \sum_{v\in son_u}f[v]\cdot prime[sz[v]]\)
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef uint64_t ull;
const int MAXN = 2e5+7;
vector<int> prime;
void sieve(){
vector<bool> pm(MAXN,true);
for(int i = 2; i < MAXN; i++){
if(pm[i]) prime.push_back(i);
for(int j = 0; j < (int)prime.size(); j++){
if(i*prime[j]>=MAXN) break;
pm[i*prime[j]] = false;
if(i%prime[j]==0) break;
}
}
}
int n;
struct Tree{
vector<int> G[MAXN];
map<string,int> msk;
string name[MAXN];
int sz[MAXN],maxsz[MAXN];
ull hashval[MAXN];
int tot,root;
void clear(){
for(int i = 1; i <= tot; i++) G[i].clear();
tot = 0;
msk.clear();
}
int getID(string &s){
if(!msk.count(s)){
msk[s] = ++tot;
name[tot] = s;
}
return msk[s];
}
void dfs(int u, int f){
sz[u] = 1; maxsz[u] = 0;
for(int v : G[u]){
if(v==f) continue;
dfs(v,u);
sz[u] += sz[v];
maxsz[u] = max(maxsz[u],sz[v]);
}
maxsz[u] = max(maxsz[u],tot-sz[u]);
}
void getHash(int u, int f){
sz[u] = 1;
hashval[u] = 1ull;
for(int v : G[u]){
if(v==f) continue;
getHash(v,u);
sz[u] += sz[v];
hashval[u] += hashval[v] * prime[sz[v]];
}
}
}tr[2];
void match(int u0, int u1, int f0, int f1){
cout << tr[0].name[u0] << ' ' << tr[1].name[u1] << endl;
tr[0].hashval[f0] = UINT64_MAX;
tr[1].hashval[f1] = UINT64_MAX;
sort(tr[0].G[u0].begin(),tr[0].G[u0].end(),[&](const int &x, const int &y){
return tr[0].hashval[x] < tr[0].hashval[y];
});
sort(tr[1].G[u1].begin(),tr[1].G[u1].end(),[&](const int &x, const int &y){
return tr[1].hashval[x] < tr[1].hashval[y];
});
int m = (int)tr[0].G[u0].size() - (f0==0?0:1);
for(int i = 0; i < m; i++)
match(tr[0].G[u0][i],tr[1].G[u1][i],u0,u1);
}
void solve(){
tr[0].clear(); tr[1].clear();
for(int t = 0; t < 2; t++){
for(int i = 1; i < n; i++){
string s1, s2;
cin >> s1 >> s2;
int u = tr[t].getID(s1);
int v = tr[t].getID(s2);
tr[t].G[u].push_back(v);
tr[t].G[v].push_back(u);
}
}
tr[0].dfs(1,0);
int hsz = *min_element(tr[0].maxsz+1,tr[0].maxsz+1+n);
for(int i = 1; i <= n; i++){
if(tr[0].maxsz[i]==hsz){
tr[0].root = i;
break;
}
}
tr[0].getHash(tr[0].root,0);
ull hax = tr[0].hashval[tr[0].root];
tr[1].dfs(1,0);
for(int i = 1; i <= n; i++){
if(tr[1].maxsz[i]==hsz){
tr[1].getHash(i,0);
if(hax==tr[1].hashval[i]){
tr[1].root = i;
break;
}
}
}
match(tr[0].root,tr[1].root,0,0);
}
int main(){
____();
sieve();
while(cin >> n) solve();
return 0;
}
HDU5732 Subway【树重心 树哈希】的更多相关文章
- B+树索引和哈希索引的区别——我在想全文搜索引擎为啥不用hash索引而非得使用B+呢?
哈希文件也称为散列文件,是利用哈希存储方式组织的文件,亦称为直接存取文件.它类似于哈希表,即根据文件中关键字的特点,设计一个哈希函数和处理冲突的方法,将记录哈希到存储设备上. 在哈希文件中,是使用一个 ...
- MySQL B+树索引和哈希索引的区别
导读 在MySQL里常用的索引数据结构有B+树索引和哈希索引两种,我们来看下这两种索引数据结构的区别及其不同的应用建议. 二者区别 备注:先说下,在MySQL文档里,实际上是把B+树索引写成了BT ...
- B+树索引和哈希索引的区别[转]
导读 在MySQL里常用的索引数据结构有B+树索引和哈希索引两种,我们来看下这两种索引数据结构的区别及其不同的应用建议. 二者区别 备注:先说下,在MySQL文档里,实际上是把B+树索引写成了BTRE ...
- MySQL B+树索引和哈希索引的区别(转 JD二面)
导读 在MySQL里常用的索引数据结构有B+树索引和哈希索引两种,我们来看下这两种索引数据结构的区别及其不同的应用建议. 二者区别 备注:先说下,在MySQL文档里,实际上是把B+树索引写成了BTRE ...
- Atitit 常见的树形结构 红黑树 二叉树 B树 B+树 Trie树 attilax理解与总结
Atitit 常见的树形结构 红黑树 二叉树 B树 B+树 Trie树 attilax理解与总结 1.1. 树形结构-- 一对多的关系1 1.2. 树的相关术语: 1 1.3. 常见的树形结构 ...
- 字典树(Trie树)的实现及应用
>>字典树的概念 Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构,如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树.与二叉查找树不同,Trie树的 ...
- 【Todo】字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树
另开一文分析字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树. 先来一个汇总, 算法: 本文中提到的字符串匹配算法有:KMP, BM, Horspool, Sunday, BF, ...
- 【bzoj1901】dynamic ranking(带修改主席树/树套树)
题面地址(权限题) 不用权限题的地址 首先说说怎么搞带修改主席树? 回忆一般的kth问题,我们的主席树求的是前缀和,这样我们在目标区间的左右端点的主席树差分下就能求出kth. 那么我们如何支持修改操作 ...
- 字典树 trie树 学习
一字典树 字典树,又称单词查找树,Trie树,是一种树形结构,哈希表的一个变种 二.性质 根节点不包含字符,除根节点以外的每一个节点都只包含一个字符: 从根节点到某一节点,路径上经过的字符串连接起 ...
随机推荐
- cookie和session会话技术
因为http协议是无状态的,也就是说每个客户端访问服务器端资源时,服务器并不知道该客户端是谁,所以需要会话技术识别客户端状态.会话技术是帮助服务器记住客户端状态的. 一次会话的开始是通过浏览器访问某个 ...
- Nginx 安装与配置教程
标签: Nginx Linux Windows 配置 描述: Ubuntu 下以及 Windows 下 Nginx 的配置:配置详解:有关 Nginx 如何配置 Nginx 在 Ubuntu 下的安装 ...
- 谈谈你不知道的gist
1.Gist是什么关于Gist的详细介绍,请阅读官方文档About gists,下面只简略介绍部分功能: Gist是一种与其他人共享代码片段和粘贴的简单方法. 当您需要与同事或朋友共享示例代码或技术时 ...
- Centos 安装 Node-v12.17.0-linux-x64.tar.gz
wget https://nodejs.org/dist/v12.17.0/node-v12.17.0-linux-x64.tar.gz tar -zxf node-v12.17.0-linux-x6 ...
- 深入理解Redis之简单动态字符串
目录 SDS SDS与C字符串的区别 SDS获取字符串长度复杂度为O(1),C字符串为O(N) SDS杜绝了缓存区溢出 减少修改字符串时带来的内存重分配次数 二进制安全 Redis没有直接使用C语言传 ...
- 分布式系统:xxl-job改造spring-cloud
目录 改造原因 主要改造思路 调度中心 调度中心 执行器侧 总结 修改后的源码仓库地址:GitHub. : 改造原因 原有的xxl-job使用自己实现的http协议进行注册以及调度等,与目前框架中本身 ...
- centos7制作U盘启动盘-九五小庞
一.准备相关软件 1.8G以上U盘 2.UltraISO虚拟光驱(试用版即可)最新版 下载地址:https://cn.ultraiso.net/xiazai.html 点击下载试用 3.CentOS ...
- Linux内存 free 详解
在Linux下,使用top命令看到内存占用情况: Mem: 4146788k total, 3825536k used, 321252k free, 213488k buffers Swap: ...
- jackson学习之四:WRAP_ROOT_VALUE(root对象)
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Linux更改密码报错:密码未通过字典检查 - 过于简单化/系统化
Linux更改密码报错:密码未通过字典检查 - 过于简单化/系统化 方案一:直接忽略 很容易认为这儿是一个错误,其实可以直接忽略,重新输入密码 [root@localhost ~]# passwd 更 ...