无根树同构_hash
先贴上地址 https://vjudge.net/problem/HDU-5732
判断有根树同构:
1. 直接用括号最小表示法
2. 利用括号最小表示法的思想进行hash
判断无根树同构:
1. 找到树的重心.
2. 以重心为根, 把无根树转化成有根树. 按照有根树同构的方法判断是否同构.
同构的过程中,为什么可以sort.
我们知道,对于树来说,
树的节点绕着它的父节点旋转,树的结构就不会被改变的.
所以sort的过程就相当于把树的节点绕着它的父节点进行旋转.
// sort的话,可以这么理解:
我们是按照同样的规则(我们保证这个规则可以唯一确定一棵树,),
对两棵树进行操作,如果同构的话,那么结果应该是一样的. 如果不同构的画 那么结果就是不一样的
至于树的括号表达式, 可以见这几个博客
括号表达式 https://www.byvoid.com/zhs/blog/directed-tree-bracket-sequence
树同构 https://blog.csdn.net/u010152669/article/details/9116975
树的表示方法 https://www.cnblogs.com/jsawz/p/6807636.html
#include <cstdio> #include <ctime> #include <cstdlib> #include <cstring> #include <algorithm> #include <map> #include <vector>using namespace std;typedef unsigned long long ull; const int maxn = 1e5+10; ull x[maxn]; int ans[maxn];struct Edge {int lst;int to; };class Tree { public :Edge edge[maxn<<1];int head[maxn];int cn, csz, ccnt, mid[3];int rcd[maxn];ull cnode[maxn];ull vvvvv[3];map<string, int> id;char name[maxn][16];inline void add(int u, int v) {edge[csz].lst = head[u];edge[csz].to = v;head[u] = csz++;}int dfs(int u, int fa) {int i, v, res = 0, t1;for (i=head[u]; i; i=edge[i].lst) {v = edge[i].to;if (v == fa) continue;t1 = dfs(v, u);res += t1;if (rcd[u] < t1) rcd[u] = t1;if (rcd[v] < cn-t1) rcd[v] = cn-t1; }return res + 1;}ull dfs2(int u, int fa, int deep) {int i, v, res = 0, t1;vector<ull> son;for (i=head[u]; i; i=edge[i].lst) {v = edge[i].to;if (v == fa) continue; son.push_back(dfs2(v, u, deep+1));}sort(son.begin(), son.end()); // 判断树同构 注意要sort后乘一个随机数(或者一个质数的i次方). 为什么可以sort呢? 因为树同一层的节点围绕父节点旋转不会改变树的结构. 而sort相当于把节点绕父节点旋转了. for (i=0, t1=son.size(); i<t1; ++i) res += son[i] * x[i+1];return cnode[u] = (res ? res : x[deep]);}void init(int n) {cn = n; csz = 1; id.clear();int i, u, v, cnt = 1;char s1[16], s2[16];for (i=1; i<=n; ++i) rcd[i] = head[i] = 0;for (i=1; i<n; ++i) {scanf("%s%s", s1, s2);if (!(u = id[s1])) {strcpy(name[cnt], s1);id[s1] = u = cnt++;}if (!(v = id[s2])) {strcpy(name[cnt], s2);id[s2] = v = cnt++;}add(u, v); add(v, u);}dfs(1, -1);int mm = 0x3f3f3f3f;for (i=1; i<=n; ++i) {if (mm > rcd[i]) {mm = rcd[i];ccnt = 0;mid[++ccnt] = i;} else if (mm == rcd[i]) mid[++ccnt] = i;}for (i=1; i<=ccnt; ++i) vvvvv[i] = dfs2(mid[i], -1, 1);} }te1, te2;struct nobe {int id;ull val;bool operator < (const nobe &a) const {return val < a.val;}nobe () {}nobe (int iid, ull vval) : id(iid), val(vval) {} };void dfs3(int u1, int u2, int fa1, int fa2) {int i, v1, v2, tsz;ans[u1] = u2;vector<nobe> ve1, ve2;for (i=te1.head[u1]; i; i=te1.edge[i].lst) {v1 = te1.edge[i].to;if (v1 == fa1) continue;ve1.push_back(nobe(v1, te1.cnode[v1]));}for (i=te2.head[u2]; i; i=te2.edge[i].lst) {v2 = te2.edge[i].to;if (v2 == fa2) continue;ve2.push_back(nobe(v2, te2.cnode[v2]));}sort(ve1.begin(), ve1.end());sort(ve2.begin(), ve2.end());for (i=0, tsz=ve1.size(); i<tsz; ++i) dfs3(ve1[i].id, ve2[i].id, u1, u2); }int main() {int i, j, k, n;srand(time(NULL));for (i=0; i<maxn; ++i) x[i] = rand();while (~scanf("%d", &n)) {te1.init(n);te2.init(n);for (i=1; i<=te1.ccnt; ++i) for (j=1; j<=te2.ccnt; ++j) {if (te1.vvvvv[i] == te2.vvvvv[j]) {dfs3(te1.mid[i], te2.mid[j], te1.mid[i], te2.mid[j]);for (k=1; k<=n; ++k) printf("%s %s\n", te1.name[k], te2.name[ans[k]]);goto A;}}A: ;}return 0; }
转载于:https://www.cnblogs.com/cgjh/p/9441605.html
无根树同构_hash相关推荐
- BZOJ 3162 独钓寒江雪(树同构计数)
给定一棵无根树,求其中本质不同的独立集的个数. 无根树同构. 转化成以重心为根的有根树,如果重心有两个,就在这两个重心之间插入一个点与这两个重心连边,这个点作为新的重心. 然后就成了有根树同构过程树形 ...
- 哈希算法在判定树同构方面的应用(上)
哈希算法在判定树同构方面的应用(上) (一)需要掌握的前置知识: (1)素数筛法:埃氏筛或者欧拉筛均可以. 以下为欧拉筛: const int maxn=100100; int p[maxn],cnt ...
- 哈希算法在判定树同构方面的应用(下)
哈希算法在判定树同构方面的应用 在上一篇文章中我们介绍了 枚举根节点哈希 和 求重心哈希 两种方法来判断两棵无根树是否同构. 但是如果有些题目中我必须要计算出每个根节点的 fff 值,且 n≤1e5n ...
- 无根树的同构:Hash最小表示法(bzoj 4337: BJOI2015 树的同构)
这里的同构是指: 对于两棵树A, B,如果能通过重新标号使得两棵树完全相同,则称树A和B同构 Hash最小表示法步骤: ①暴力每个节点为根 ②对于当前根x,对树进行DFS ③DFS时对每个节点维护一个 ...
- java 树同构_有根树的同构 和 无根树的同构
#include#include#include#include#includeusingnamespacestd;constintMod=9901;constintMax=1010;//节点数con ...
- [BJOI2015]树的同构
嘟嘟嘟 判断树的同构的方法就是树上哈希. 如果树是一棵有根树,那么只要从根节点出发dfs,每一个节点的哈希值等于按传统方式算出来的子树的哈希值的结果.需要注意的是,算完子树的哈希值后要先排序再加起来, ...
- [BJOI2015] 树的同构
4337: BJOI2015 树的同构 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 1092 Solved: 460 [Submit][Stat ...
- 树的同构模板题(法1.最小表示法+法2.树哈希)
树的同构 problem solution code solution code problem 模板题 solution Ⅰ. 最小表示法 将树转化为 0/10/10/1 括号序列:从根开始 dfs ...
- 【BZOJ - 4337】BJOI2015 树的同构(树哈希)
题干: 树是一种很常见的数据结构. 我们把N个点,N-1条边的连通无向图称为树. 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树. 对于两个树T1和T2,如果能够把树T1的 ...
最新文章
- Pycharm安装PyQT5调用QTDesigner
- JavaScript对象根据自定义属性进行排序
- Photoshop图像修饰工具
- React开发(248):react项目理解 ant design input autosize
- 手把手maven的功能/安装/使用/idea集成
- 信息学奥赛一本通C++语言——1078:求分数序列和
- mysql jdbc百度_mysql8.0 jdbc连接注意事项
- Qt中焦点策略FocusPolicy的使用
- 新加坡推出人工智能计划AI.SG 迎战人工智能和数据科学关键难题
- python制作个人名片_python做名片系统
- php 万能密码,万能用户名和万能密码
- 阿里云2核4G云服务器租用CPU内存、公网带宽和系统盘配置
- RootTools.jar API
- Entity Framework基础
- 路由与交换技术第六章
- 新生儿登记-申办报告
- 苏宁易购商品详情 API
- Lyapunov直接法与间接法
- mysql iops nvme_硬盘性能指标之一的IOPS,今天带你看懂
- 职场:IT女性的困扰
热门文章
- 正版鬼泣手游服务器,爆款频出!永劫无间+鬼泣正版手游,国内掀起硬核游戏风潮...
- 两个月突袭java_Java面试突击系列-基础篇
- 校安行 |“熊孩子”出没无影踪?暑期安全防范不能忽视
- python爬虫下载小说_python 爬取小说并下载的示例
- QianWei搭建属于自己的音乐网站,并可远程访问
- 硅谷战争:苹果谷歌微软上演三国大战
- 击败DotA2顶级人类玩家,并不是AI的一次突破
- android7.0 静默安装
- 在知乎上看到的一个电话诈骗的文章
- android培训班 多少钱,Android培训班(42) --Make