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. 关于Object.defineProperty的get和set

    面试经常提问vue双向数据绑定的原理,其主要是依赖于Object.definePropety(); Object.definePropety下面有get和set方法. get指读取属性时调用的放法,s ...

  2. 使用gradle构建Android时 版本号versionName中嵌入git提交信息

    为什么要这么做   在应用开发的版本迭代过程中,通过版本号并不能快速定位到所对应的代码,导致在后面分析问题追溯对应版本的代码时比较麻烦.   如果代码是通过git来管理的,git的commit id等 ...

  3. [Spring MVC - 2A] - java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)

    严重: Servlet.service() for servlet [springMVC] in context with path [/ExceptionManageSystem] threw ex ...

  4. javascript 自定义Map

      迁移时间:2017年5月25日08:24:19 Author:Marydon 三.自定义Map数据格式 需特别注意的是: js中没有像java中的Map数据格式,js自带的map()方法用于:返回 ...

  5. Android设计模式(八)--模板方法模式

    到国美面试Android的时候.问我的设计模式相关的问题: 1.单例模式的意义时什么. 2.有哪几种工厂方法模式: 3.你用过的模板方法模式.举例说明: 自己感觉答的一塌糊涂. 模板方法模式都没说出来 ...

  6. Drupal启动阶段之六:页面头信息

    Drupal在本阶段为用户设置缓存头信息.Drupal不为验证用户缓存页面,每次请求时都是从新读取的. function _drupal_bootstrap_page_header() { boots ...

  7. 【Linux设备驱动程序】Chapter 2 - 构造和运行模块

    Hello World 模块 #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Du ...

  8. mongodb - mongostat说明

    # ./mongostat insert query update delete getmore command % dirty % used flushes vsize res qr|qw ar|a ...

  9. 【Java集合源代码剖析】TreeMap源代码剖析

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/36421085 前言 本文不打算延续前几篇的风格(对全部的源代码加入凝视),由于要理解透Tr ...

  10. .NET面试题(二)

    基础方面: 1.简单的描述一下C# 中重写,重载,隐藏的概念 C#中重写(overide)是子类继承父类后,对父类中的方法进行行为改写. 重载是指方法名相同,参数不同 重写和隐藏的定义: 重写:基类方 ...