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树,是一种树形结构,哈希表的一个变种 二.性质 根节点不包含字符,除根节点以外的每一个节点都只包含一个字符: 从根节点到某一节点,路径上经过的字符串连接起 ...
随机推荐
- jquery表格插件Datatables使用、快速上手
Datatables使用 一.简介 官网:https://datatables.net/ 中文官网:http://datatables.club/ Datatables是一款jquery表格插件.它是 ...
- LeetCode198--打家劫舍问题
题目 你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警. 给定一个 ...
- 断言封装之key检查及kv实战示例
️️️️️️️️️️️️️️️️️️️️️️️️️️️️️ 测试: 断言处理: demo_04.pyimport jsonjson_obj = {"access_token":&q ...
- SQLI-LABS复现通关
sql-lab 复现通关(深入学习) less-1 基于错误的单引号字符串 - 正常访问 127.0.0.1/?id=1 - 添加 ' 返回报错信息:You have an error in your ...
- 【Oracle】下载11.2.0.4的地址
https://updates.oracle.com/download/13390677.html 这个地址就是下载Oracle 11.2.0.4版本的地址,需要有metalink账号才可以下载
- Tippy.js - 免费开源且高度可定制的气泡提示独立组件
推荐一个非常优秀的 web 气泡提示独立UI组件. 介绍 Tippy.js 是一款用于Web的完整工具提示,弹出菜单,下拉菜单和菜单解决方案.适用于鼠标,键盘和触摸输入. 特点 超轻量的纯 javas ...
- 关于postgresql中numeric和decimal的精度和标度问题
精度即数的有效数字个数 2.5的有效数字个数是2,但是053.2的有效数字个数是3 标度是小数点的位数 例如numeric(2,1),即这个数必须是两位,并且小数后面最多有一位,多出来的小数会被四舍五 ...
- UVM基础总结——基于《UVM实战》示例
一.前言 工作一直在做SoC验证,更关注模块间的连接性和匹配性,所以相比于擅长随机约束激励的UVM来说,定向测试的概念更容易debug.当然前提是IP已经被充分验证.因此觉得接触UVM的机会较少.到现 ...
- Java程序入门
编写Java源程序 在d:\day01 目录下新建文本文件,完整的文件名修改为HelloWorld.java ,其中文件名为HelloWorld ,后缀名必须为.java . 用记事本打开 在文件中键 ...
- TekRADIUS5.5安装教程
1.下载地址:https://www.kaplansoft.com/TekRADIUS/release/tekradius.zip 2.解压安装,双击一步默认安装下来就是了 3.配置连接数据库: 4. ...