刷题总结——树的同构(bzoj4337 树上hash)
Description
树是一种很常见的数据结构。
我们把N个点,N-1条边的连通无向图称为树。
若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树。
对于两个树T1和T2,如果能够把树T1的所有点重新标号,使得树T1和树T2完全相
同,那么这两个树是同构的。也就是说,它们具有相同的形态。
现在,给你M个有根树,请你把它们按同构关系分成若干个等价类。
Input
第一行,一个整数M。
接下来M行,每行包含若干个整数,表示一个树。第一个整数N表示点数。接下来N
个整数,依次表示编号为1到N的每个点的父亲结点的编号。根节点父亲结点编号为0。
Output
输出M行,每行一个整数,表示与每个树同构的树的最小编号。
Sample Input
4
4 0 1 1 2
4 2 0 2 3
4 0 1 1 1
4 0 1 2 3
Sample Output
1
1
3
1
HINT
【样例解释】
编号为1, 2, 4 的树是同构的。编号为3 的树只与它自身同构。
100% 的数据中,1 ≤ N, M ≤ 50。
题解:
通过树上hash解决树的同构问题的模板题···
先说如何进行树上hash,设f[i]为以i为节点的hash值,则
f[i]=sigma(f[j]*prime[j]) j为son[i]
其中prime为预处理出来的素数表···注意f[j]需要进行排序····
然后对于两颗待判定的树,将两颗树分别以树上每一个节点为根节点求hash值··将根节点的hash值储存起来排序然后两颗树一一比对··如果完全一样则两棵树就一样
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<cstring> #include<string> #include<algorithm> using namespace std; const int N=55; int hash[N][N],n,que[N]; int tot,fst[N],nxt[N*2],go[N*2],f[N]; int prime[]={0,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317}; inline void comb(int a,int b) {nxt[++tot]=fst[a],fst[a]=tot,go[tot]=b;nxt[++tot]=fst[b],fst[b]=tot,go[tot]=a; } inline void dfs(int u,int fa) {unsigned int st[N];int tot=0; st[++tot]=1;for(int e=fst[u];e;e=nxt[e]){int v=go[e];if(v==fa) continue;dfs(v,u);st[++tot]=f[v];}f[u]=0;sort(st+1,st+tot+1);for(int i=1;i<=tot;i++) f[u]+=st[i]*prime[i]; } int main() {// freopen("a.in","r",stdin);scanf("%d",&n);int a,b;for(int i=1;i<=n;i++){scanf("%d",&a);memset(fst,0,sizeof(fst));tot=0;for(int j=1;j<=a;j++) {scanf("%d",&b);if(b) comb(j,b);}for(int j=1;j<=a;j++){dfs(j,0);hash[i][j]=f[j];}sort(hash[i]+1,hash[i]+a+1);for(int j=1;j<=i;j++){bool flag=true;for(int k=1;k<=a;k++)if(hash[j][k]!=hash[i][k]) { flag=false;break;}if(flag==true) { printf("%d\n",j);break;}}}return 0; }
转载于:https://www.cnblogs.com/AseanA/p/7633174.html
刷题总结——树的同构(bzoj4337 树上hash)相关推荐
- leetcode刷题之树(三)
翻转二叉树,感觉做二叉树的问题好像都是那一套公式,除了个别的问题解决不了,用上篇博客leetcode刷题之树(二)的模型基本可以解决.总体来说就是树基本都可以利用递归和迭代的方法去解决,在涉及到树的遍 ...
- 【LeetCode 剑指offer刷题】树题6:28 对称二叉树(101. Symmetric Tree)
[LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) 101. Symmetric Tree /** * Definition for a binary tree no ...
- 【LeetCode 剑指offer刷题】树题16:Kth Smallest Element in a BST
[LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) Kth Smallest Element in a BST Given a binary search tree, ...
- C#LeetCode刷题-线段树
线段树篇 # 题名 刷题 通过率 难度 218 天际线问题 32.7% 困难 307 区域和检索 - 数组可修改 42.3% 中等 315 计算右侧小于当前元素的个数 31.9% 困难 493 翻转对 ...
- C#LeetCode刷题-字典树
字典树篇 # 题名 刷题 通过率 难度 208 实现 Trie (前缀树) 48.6% 中等 211 添加与搜索单词 - 数据结构设计 39.9% 中等 212 单词搜索 II 27.9% 困难 33 ...
- 【LeetCode 剑指offer刷题】树题19:8 二叉树中序遍历的下一个结点
[LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) 8 二叉树中序遍历的下一个结点 题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注 ...
- 【LeetCode 剑指offer刷题】树题4:104 Maximum Depth of Binary Tree
[LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) 104. Maximum Depth of Binary Tree Given a binary tree, fin ...
- 【2019暑假刷题笔记-树的遍历】总结
关于树这一块,前期没有做一个学习的绪论,因为时间来不及了.在总结上回顾一下这些题目的一些特点 树的遍历的是数据结构树这一块中的一部分. 树的遍历和二叉树的遍历本质上相同.二叉树用指针也可以做,但是在考 ...
- leetcode刷题之树(1)
提到树首先肯定是树的三个遍历即前中后 序遍历.树的遍历可以通过两种方式实现,一种是最常见的最简单递归,一种是借用栈来进行迭代.虽然两者实现的形式不一样,但是两者的思想是一样的.都是有点类似于回溯算法的 ...
最新文章
- wxWidgets:存档格式
- node.js基础:数据存储
- 循环服务器,并发服务器模型以及I/O多路转接模型
- Numpy实现酒鬼漫步问题【以及randint()、where()、cumsum()、argmax()的用法详解】
- 单片机拼字程序怎么做_餐饮怎么用微信小程序?餐饮行业怎么做小程序
- Python sorted() 函数
- RPG 学习 一 基本
- 计算机学号生成准考证号,设计考场编排,生成准考证号
- lora终端连接云服务器_一种LoRa服务器及其数据传输方法与流程
- cs服务器网页管理端,sXe服务器端怎么管理
- 线性分类器定义和局限性
- Java最新手机号正则验证
- ScrollView 滑动停止监听
- Expert 诊断优化系列------------------内存不够用么?
- python html5游戏_25 个超棒的 HTML5 JavaScript 游戏引擎开发库
- android动画机制,Android动画机制探究
- PageRank算法 -- 图算法
- 树形结构——JAVA实现
- 【掘金Shopee蓝海】教你如何使用知虾找到蓝海?
- 一站式VIP客服中心解决方案