Subway (树中心 + 树hash)
首先找到树的中心或者中心,我这里是找中心,因为我们需要找一个相同的起点,然后最多2个中心就是树的宽度为偶数时,奇数时为1个。
找到之后需要对树进行hash,使得每个点都具备独特性,使之树的形态能够保证唯一,然后利用hash值,对树的每个节点下的节点进行排序,之后如果判定这两个树是一样的话,我只需要对树进行一次深搜并把遍历的顺序存进数组。然后直接按照数组中的值输出原来映射的字符串就好了。
#include<bits/stdc++.h>
#define LL long long
using namespace std; const int mod = 1e9 + ;
const int maxn = 1e5 + ;
const int seed = ;
char inp[], onp[]; struct Tree{
map<string, int>id;
vector<int>edge[maxn];
string anw[maxn], rip[maxn];
int _cnt, ctr[], siz[maxn], dep[maxn], fa[maxn];
LL Har[maxn]; ///将遍历顺序存进去
void done(int st, int fa){
if(fa == ) _cnt = ;
anw[_cnt ++] = rip[st];
for(auto x : edge[st]){
if(x == fa) continue;
done(x, st);
}
} ///hash技术
LL dfsh(int st, int fa){
Har[st] = seed;siz[st] = ;
for(auto x : edge[st]){
if(x == fa) continue;
dfsh(x, st);
siz[st] += siz[x];
}
sort(edge[st].begin(), edge[st].end(),
[&](int x, int y){return Har[x] < Har[y];});
for(auto x : edge[st]){
if(x == fa) continue;
Har[st] = (((Har[st] * Har[x]) % mod) ^ Har[x])% mod;
}
Har[st] = (Har[st] + siz[st]) % mod;
Har[st] = (Har[st] * Har[st]) % mod;
return Har[st];
} ///得到深度值
void getdep(int st, int Fa, int Dep){
dep[st] = Dep;fa[st] = Fa;
for(auto x : edge[st]){
if(x == fa[st]) continue;
getdep(x,st,Dep + );
}
} ///获取中点
void getCtr(int n){
getdep(, , );
ctr[] = max_element(dep + , dep + + n) - dep;
getdep(ctr[], , );
ctr[] = max_element(dep + , dep + + n) - dep;
int fdep = dep[ctr[]];
for(int i = ; i < fdep/; i ++)
ctr[] = fa[ctr[]];
ctr[] = ctr[];
if(fdep & ) ctr[] = fa[ctr[]];
} ///重置数据
void init(int n){
for(int i = ; i <= n; i ++)
edge[i].clear();
id.clear();_cnt = ;
} ///映射连接的符号,并存进对应的map值为下标的地方
int toid(string v){
if(id.find(v) != id.end()) return id[v];
rip[_cnt] = v;
return id[v] = _cnt ++;
} ///建图,映射值
void input(int n){
init(n);int l,r;
for(int i = ; i < n; i ++){
scanf("%s %s", inp, onp);
l = toid(inp); r = toid(onp);
edge[l].push_back(r);
edge[r].push_back(l);
}
}
}X, Y; void solve(){
for(int i = ; i < ; i ++)
for(int j = ; j < ; j ++)
if(X.dfsh(X.ctr[i], ) == Y.dfsh(Y.ctr[j], )){
X.done(X.ctr[i], );
Y.done(Y.ctr[j], );
return;
}
} int main(){
int n;while(~scanf("%d", &n)){
X.input(n);
Y.input(n);
X.getCtr(n);
Y.getCtr(n);
solve();
for(int i = ; i < n; i ++)
printf("%s %s\n",X.anw[i].c_str(), Y.anw[i].c_str());
}return ;
}
这次的代码可以说是照搬过来的,菜鸡的自己。
Subway (树中心 + 树hash)的更多相关文章
- bzoj 1669: [Usaco2006 Oct]Hungry Cows饥饿的奶牛【dp+树状数组+hash】
最长上升子序列.虽然数据可以直接n方但是另写了个nlogn的 转移:f[i]=max(f[j]+1)(a[j]<a[i]) O(n^2) #include<iostream> #in ...
- MySQL的B+树索引和hash索引的区别
简述一下索引: 索引是数据库表中一列或多列的值进行排序的一种数据结构:索引分为聚集索引和非聚集索引,聚集索引查询类似书的目录,快速定位查找的数据,非聚集索引查询一般需要再次回表查询一次,如果不使用索引 ...
- 字符串 --- KMP Eentend-Kmp 自动机 trie图 trie树 后缀树 后缀数组
涉及到字符串的问题,无外乎这样一些算法和数据结构:自动机 KMP算法 Extend-KMP 后缀树 后缀数组 trie树 trie图及其应用.当然这些都是比较高级的数据结构和算法,而这里面最常用和最熟 ...
- 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))
函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...
- 【Todo】字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树
另开一文分析字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树. 先来一个汇总, 算法: 本文中提到的字符串匹配算法有:KMP, BM, Horspool, Sunday, BF, ...
- 剑指Offer——Trie树(字典树)
剑指Offer--Trie树(字典树) Trie树 Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种的单词.对于每一个单词,我们要判断他出没出现过,如果出现了,求第一次出现在第几个位 ...
- 主席树套树状数组——带修区间第k大zoj2112
主席树带修第k大 https://www.cnblogs.com/Empress/p/4659824.html 讲的非常好的博客 首先按静态第k大建立起一组权值线段树(主席树) 然后现在要将第i个值从 ...
- HDU4819 Mosaic【树套树】
LINK 题目大意 给你一个\(n*n\)矩阵,每个点有初始权值 q次询问每次把一个矩形的中心节点变成这个矩形中最大值和最小值的平均数 思路 很显然的树套树啊 就是一开始傻逼了没想到怎么去维护这个东西 ...
- HDU 4605 Magic Ball Game(可持续化线段树,树状数组,离散化)
Magic Ball Game Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
随机推荐
- 九九乘法表python3写入文件中
写入文件代码如下: with open("e:\\test01.txt","w+",encoding="utf-8") as wq: for ...
- HashMap如何解决取Value值为Null
场景: 用HashMap方法时候,取Keys时候自认为敲的肯定是准确无误,然后能得到对应的Values 值. 但写脚本代码时候不好习惯,没事总喜欢敲个空格建,导致取Keys之后多空格. Featur ...
- 新兴的API(fileReader、geolocation、web计时、web worker)
requestAnimationFrame() 每次浏览器重绘之前会调用这个方法!!! 它接收一个参数,就是回调函数: 它可以保证在最佳的间隔时间调用传入的回调函数,以达到让屏幕产生最流畅的动画效果. ...
- django时间的时区问题(转)
add by zhj: 使用django时,如果设置USE_TZ=True,那django在数据库中存储的是0时区的时间:如果USE_TZ=False,那存储的是本地时间 原文:https://www ...
- Jenkins tomcat打包启动脚本,待完善
shell脚本 #!/bin/bashJENKINS_HOME=/usr/local/jenkinsTOMCAT_HOME=/usr/local/jenkins/tomcat-testSHUTDOWN ...
- python的队列和栈
(一)队列和栈的区别 1.队列: 队列是一种特殊的线性表.其两头都有限制,插入只能在表的一端进行(只进不出),而删除只能在表的另一端进行(只出不进),允许删除的一端称为队尾(rear),允许插入的一端 ...
- mysql 内置功能目录
mysql 内置功能 视图介绍 mysql 内置功能 视图 使用 mysql 内置功能 触发器介绍 mysql 内置功能 触发器 实验 mysql 内置功能 事务 介绍 mysql 内置功能 存储过程 ...
- MySQL复制异常大扫盲:快速溯源与排查错误全解
MySQL复制异常大扫盲:快速溯源与排查错误全解https://mp.weixin.qq.com/s/0Ic8BnUokyOj7m1YOrk1tA 作者介绍王松磊,现任职于UCloud,从事MySQL ...
- RestFramework——API基本实现及dispatch基本源码剖析
基于Django实现 在使用RestFramework之前我们先用Django自己实现以下API. API完全可以有我们基于Django自己开发,原理是给出一个接口(URL),前端向URL发送请求以获 ...
- vue-element-dialog使用
logout() { this.$confirm("你确定退出吗?", "提示:", { confirmButtonText: "确定", ...