先贴上地址 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相关推荐

  1. BZOJ 3162 独钓寒江雪(树同构计数)

    给定一棵无根树,求其中本质不同的独立集的个数. 无根树同构. 转化成以重心为根的有根树,如果重心有两个,就在这两个重心之间插入一个点与这两个重心连边,这个点作为新的重心. 然后就成了有根树同构过程树形 ...

  2. 哈希算法在判定树同构方面的应用(上)

    哈希算法在判定树同构方面的应用(上) (一)需要掌握的前置知识: (1)素数筛法:埃氏筛或者欧拉筛均可以. 以下为欧拉筛: const int maxn=100100; int p[maxn],cnt ...

  3. 哈希算法在判定树同构方面的应用(下)

    哈希算法在判定树同构方面的应用 在上一篇文章中我们介绍了 枚举根节点哈希 和 求重心哈希 两种方法来判断两棵无根树是否同构. 但是如果有些题目中我必须要计算出每个根节点的 fff 值,且 n≤1e5n ...

  4. 无根树的同构:Hash最小表示法(bzoj 4337: BJOI2015 树的同构)

    这里的同构是指: 对于两棵树A, B,如果能通过重新标号使得两棵树完全相同,则称树A和B同构 Hash最小表示法步骤: ①暴力每个节点为根 ②对于当前根x,对树进行DFS ③DFS时对每个节点维护一个 ...

  5. java 树同构_有根树的同构 和 无根树的同构

    #include#include#include#include#includeusingnamespacestd;constintMod=9901;constintMax=1010;//节点数con ...

  6. [BJOI2015]树的同构

    嘟嘟嘟 判断树的同构的方法就是树上哈希. 如果树是一棵有根树,那么只要从根节点出发dfs,每一个节点的哈希值等于按传统方式算出来的子树的哈希值的结果.需要注意的是,算完子树的哈希值后要先排序再加起来, ...

  7. [BJOI2015] 树的同构

    4337: BJOI2015 树的同构 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 1092  Solved: 460 [Submit][Stat ...

  8. 树的同构模板题(法1.最小表示法+法2.树哈希)

    树的同构 problem solution code solution code problem 模板题 solution Ⅰ. 最小表示法 将树转化为 0/10/10/1 括号序列:从根开始 dfs ...

  9. 【BZOJ - 4337】BJOI2015 树的同构(树哈希)

    题干: 树是一种很常见的数据结构. 我们把N个点,N-1条边的连通无向图称为树. 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树. 对于两个树T1和T2,如果能够把树T1的 ...

最新文章

  1. Pycharm安装PyQT5调用QTDesigner
  2. JavaScript对象根据自定义属性进行排序
  3. Photoshop图像修饰工具
  4. React开发(248):react项目理解 ant design input autosize
  5. 手把手maven的功能/安装/使用/idea集成
  6. 信息学奥赛一本通C++语言——1078:求分数序列和
  7. mysql jdbc百度_mysql8.0 jdbc连接注意事项
  8. Qt中焦点策略FocusPolicy的使用
  9. 新加坡推出人工智能计划AI.SG 迎战人工智能和数据科学关键难题
  10. python制作个人名片_python做名片系统
  11. php 万能密码,万能用户名和万能密码
  12. 阿里云2核4G云服务器租用CPU内存、公网带宽和系统盘配置
  13. RootTools.jar API
  14. Entity Framework基础
  15. 路由与交换技术第六章
  16. 新生儿登记-申办报告
  17. 苏宁易购商品详情 API
  18. Lyapunov直接法与间接法
  19. mysql iops nvme_硬盘性能指标之一的IOPS,今天带你看懂
  20. 职场:IT女性的困扰

热门文章

  1. 正版鬼泣手游服务器,爆款频出!永劫无间+鬼泣正版手游,国内掀起硬核游戏风潮...
  2. 两个月突袭java_Java面试突击系列-基础篇
  3. 校安行 |“熊孩子”出没无影踪?暑期安全防范不能忽视
  4. python爬虫下载小说_python 爬取小说并下载的示例
  5. QianWei搭建属于自己的音乐网站,并可远程访问
  6. 硅谷战争:苹果谷歌微软上演三国大战
  7. 击败DotA2顶级人类玩家,并不是AI的一次突破
  8. android7.0 静默安装
  9. 在知乎上看到的一个电话诈骗的文章
  10. android培训班 多少钱,Android培训班(42) --Make