https://www.hackerrank.com/contests/hourrank-21/challenges/tree-isomorphism

题目大意:

给出一棵树, 求有多少本质不同的子树。   N <= 19

下面给出我综合了网上一些做法后设计的hash函数(我不会证明碰撞概率)

判断两棵有根树是否相同:

将子树的Hash值从小到大排序, Hash(x) =  A * p xor Hash(son_1) mod q  * p  xor Hash(son_2) mod q ....  * p xor Hash(son_k) mod q * B mod q

判断两棵无根树是否相同:

找到重心 u, v(u 可能等于v, 即只有一个重心)  分别以它们为根求有根树Hash。不妨设 Hash(u) <= Hash(v)

Unrooted_Hash(x) = triple(n, u, v)  n为节点数。

对于本题, 只要暴力将每个子树的Unrooted_Hash 插入到set里就好了。

代码:

 //https://www.hackerrank.com/contests/hourrank-21/challenges/tree-isomorphism
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <set>
using namespace std; typedef long long ll; #define N 20
const int INF = << ;
const int P = , A = , B = ;
const ll mod = 1e12 + ;
const double pi = acos(-); vector<int> E[N], cone;
int size[N], cnt;
set<pair<int, pair<ll, ll> > > st; int DFS_SIZE(int x, int pre)
{
int res = ;
for (int i = ; i < E[x].size(); ++i)
{
int y = E[x][i];
if (y == pre) continue;
res += DFS_SIZE(y, x);
}
return size[x] = res;
} void Find_Cone(int x, int pre)
{
bool f = true;
for (int i = ; i < E[x].size(); ++i)
{
int y = E[x][i];
if (y == pre) continue;
Find_Cone(y, x);
if (size[y] > cnt / ) f = false;
}
if (cnt - size[x] > cnt / ) f = false;
if (f) cone.push_back(x);
} ll Hash(int x, int pre)
{
vector<ll> res;
for (int i = ; i < E[x].size(); ++i)
{
int y = E[x][i];
if (y == pre) continue;
res.push_back(Hash(y, x));
}
sort(res.begin(), res.end()); ll h = A;
for (int i = ; i < res.size(); ++i) h = (h * P ^ res[i]) % mod;
h = h * B % mod;
return h;
} int main()
{
//freopen("in.in", "r", stdin);
//freopen("out.out", "w", stdout); int n, x, y, a[], b[];
cin >> n;
for (int i = ; i < n - ; ++i) cin >> a[i] >> b[i], --a[i], --b[i];
for (int mask = ; mask < ( << n); ++mask)
{
for (int i = ; i < n; ++i) E[i].clear();
cone.clear(); cnt = ;
for (int i = ; i < n - ; ++i)
{
if ((mask & ( << a[i])) && (mask & ( << b[i])))
{
E[a[i]].push_back(b[i]);
E[b[i]].push_back(a[i]);
}
}
int root;
for (int i = ; i < n; ++i) if (mask & ( << i)) root = i, ++cnt;
if (DFS_SIZE(root, -) != cnt) continue; Find_Cone(root, -);
if (cone.size() == )
{
ll h = Hash(cone[], -);
st.insert(make_pair(cnt, make_pair(h, h)));
}
else
{
ll h1 = Hash(cone[], -), h2 = Hash(cone[], -);
if (h1 > h2) swap(h1, h2);
st.insert(make_pair(cnt, make_pair(h1, h2)));
}
}
printf("%d\n", (int)st.size());
return ;
}

Hourrank 21 Tree Isomorphism 树hash的更多相关文章

  1. 【HDU6647】Bracket Sequences on Tree(树Hash 树上Dp)

    题目链接 大意 给出一颗树,按下列方式生成一个括号序列. function dfs(int cur, int parent): print('(') for all nxt that cur is a ...

  2. CJOJ 1976 二叉苹果树 / URAL 1018 Binary Apple Tree(树型动态规划)

    CJOJ 1976 二叉苹果树 / URAL 1018 Binary Apple Tree(树型动态规划) Description 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的 ...

  3. 【数据结构】B-Tree, B+Tree, B*树介绍 转

    [数据结构]B-Tree, B+Tree, B*树介绍 [摘要] 最近在看Mysql的存储引擎中索引的优化,神马是索引,支持啥索引.全是浮云,目前Mysql的MyISAM和InnoDB都支持B-Tre ...

  4. B-Tree, B+Tree, B*树介绍

    [数据结构]B-Tree, B+Tree, B*树介绍 转   [数据结构]B-Tree, B+Tree, B*树介绍 [摘要] 最近在看Mysql的存储引擎中索引的优化,神马是索引,支持啥索引.全是 ...

  5. TZOJ 4292 Count the Trees(树hash)

    描述 A binary tree is a tree data structure in which each node has at most two child nodes, usually di ...

  6. 树hash

    判断树的同构,采用树hash的方式. 树hash定义在有根树上.判断无根树同构的时候,可以比较重心为根的hash值或者比较每个点为根的hash值. h[x]表示x为根的子树的hash,g[x]表示x为 ...

  7. POJ3237 Tree (树链剖分)

    通过打懒标记实现区间取反,和线段树基本操作都差不多. 本题还是一道边权化为点权的问题. 200行巨长代码: 1 #include<cstdio> 2 #include<cstring ...

  8. Mysql存储引擎之TokuDB以及它的数据结构Fractal tree(分形树)

    在目前的Mysql数据库中,使用最广泛的是innodb存储引擎.innodb确实是个很不错的存储引擎,就连高性能Mysql里都说了,如果不是有什么很特别的要求,innodb就是最好的选择.当然,这偏文 ...

  9. 页面设计--Tree目录树

    Tree目录树控件属性: 根据数据集合来配置相应的信息 加载模式有自动加载.自定加载 web中显示效果图:

随机推荐

  1. 屏幕录像大师如何把LXE文件转换为EXE文件

    EXE 和 LXE 实际上是同一种格式,文件大小完全相同,可以快速相互转换.区别是EXE复制到其它电脑上可以直接播放,LXE需要播放器播放,我们提供LXE播放器,而且是完全免费的.EXE的好处是复制到 ...

  2. postgresql 如何导入sql文件

    (1)不能使用pgadmin 执行Copy语句,目前客户端还不支持这种写法. (2)打开sql shell,执行如下操作 \i C:/Users/Peter_Youny/Desktop/ischool ...

  3. 怎样推断多个字段组成的keyword在另外一张表中是否存在

    怎样推断多个字段组成的keyword在另外一张表中是否存在 老帅(20141107) 1.首先推断一个keyword在另外一张表中是否存在非常easy! SELECT * FROM a WHERE a ...

  4. React.Fragment 包裹标签

    在 vue 里,我们会用 <template></template> 标签来包裹一些不能有父容器的复数同级标签. 例如在 <tbody></tbody> ...

  5. 文本域textarea

      文本域 CreateTime--2017年5月23日15:12:08Author:Marydon 二.文本域 (一)语法 <textarea></textarea> (二) ...

  6. Nunit2.5.10快速上手(笔记)

    1.下载Nunit:http://www.nunit.org/index.php?p=download,下载MSI格式的安装包: 2.安装Nunit,根据提示安装即可,没有什么需要配置的,直接下一步就 ...

  7. jmeter ---测试TCP服务器/模拟发送TCP请求

    jmeter测试TCP服务器/模拟发送TCP请求 jmeter测试TCP服务器,使用TCP采样器模拟发送TCP请求. TCP采样器:打开一个到指定服务器的TCP / IP连接,然后发送指定文本并等待响 ...

  8. 【Android】Architecture Components最佳实践--Lifecycles

    UI controllers (activities and fragments) 中代码越少越好,不应该自己去请求数据,而是用ViewModel来更新数据,并且监听LiveData来更新UI UI ...

  9. SSDB(网络LevelDB)-- 实际遇到的问题

    简介 SSDB -- 支持网络的LevelDB 站点:https://github.com/ideawu/ssdb 我实际使用了SSDB支持网络+持久化特性,完成了一个集群 1.句柄数 ulimit ...

  10. 在linux下运行jmeter

    之前在用JMeter做性能测试时基本都用自己的笔记本电脑. 考虑到网络传输和占用系统资源情况时进行了以下分析: 1 在笔记本上,开始-cmd "ping 服务器",得到传输时间.在 ...