【树hs】[BJOI2015]树的同构

题目描述
树是一种很常见的数据结构。 我们把N个点,N-1条边的连通无向图称为树。 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树。 对于两个树T1和T2,如果能够把树T1的所有点重新标号,使得树T1和树T2完全相 同,那么这两个树是同构的。也就是说,它们具有相同的形态。 现在,给你M个有根树,请你把它们按同构关系分成若干个等价类。

输入格式
第一行,一个整数M。 接下来M行,每行包含若干个整数,表示一个树。第一个整数N表示点数。接下来N 个整数,依次表示编号为1到N的每个点的父亲结点的编号。根节点父亲结点编号为0。

输出格式
输出M行,每行一个整数,表示与每个树同构的树的最小编号。

样例一
input

4
4 0 1 1 2
4 2 0 2 3
4 0 1 1 1
4 0 1 2 3
output

1
1
3
1
样例解释
编号为1, 2, 4 的树是同构的。编号为3 的树只与它自身同构。

限制与约定
对于100%的数据,1≤N,M≤501≤N,M≤50
时间限制:1s1s
空间限制:256MB

T

这道题是树hs裸题,树hs的思路就是,先把每个节点的点权赋为1,然后父节点累加子节点平方和自己的值向上返回,

就是一个递归的过程,然后自然溢出

但是每个树的根节点可能会不同,所以我们要有对于每个树选根的唯一标准

对,就是树重心,一个树可能有多个重心,那么我们只需要一个超级原点就ok 了

最后比较超级原点的hs值,就能知道是否同构

有一点玄学的地方,就是用seed的方式过不了,也不知道是为什么

 1 #include<bits/stdc++.h>
 2 #define N 100
 3 #define clear(a,val) memset(a,val,sizeof(a))
 4 using namespace std;
 5 typedef unsigned long long ult;
 6 int n,m,f,cnt=1,pp;
 7 int head[N],nxt[N*2],to[N*2],size[N],ans[N];
 8 ult vv[N],val[N];
 9 inline void add(int u,int v)
10     {nxt[cnt]=head[u],to[cnt]=v,head[u]=cnt++;}
11 inline void cl(){
12     clear(size,0),clear(ans,0),clear(head,-1),cnt=1,pp=0;
13 }
14 int dfs(int now,int fa)
15 {
16     size[now]=1;int ma=-1;
17     for(int i=head[now];i!=-1;i=nxt[i])
18     {
19         int t=to[i];
20         if(t==fa)continue;
21         size[now]+=dfs(t,now);
22         ma=max(ma,size[t]);
23     }
24     ma=max(ma,n-size[now]);
25     if(ma<=(n>>1))ans[++pp]=now;
26     return size[now];
27 }
28 inline void weigh()
29 {
30     dfs(1,-1);
31     for(int i=1;i<=pp;i++)
32         add(n+1,ans[i]);
33 }
34 ult cal(int now,int fa)
35 {
36     vv[now]=1;
37     for(int i=head[now];i!=-1;i=nxt[i])
38     {
39         int t=to[i];
40         if(t==fa)continue;
41         vv[now]+=cal(t,now);
42     }
43     return vv[now]*vv[now];
44 }
45 inline void init_build_weigh_solve()
46 {
47     clear(head,-1);
48     scanf("%d",&m);
49     for(int i=1;i<=m;i++)
50     {
51         cl();
52         scanf("%d",&n);
53         for(int j=1;j<=n;j++)
54         {
55             scanf("%d",&f);
56             if(f==0)continue;
57             else add(f,j),add(j,f);
58         }
59         weigh();
60         val[i]=cal(n+1,-1);
61     }
62     for(int i=1;i<=m;i++)
63     {
64         for(int j=1;j<=i;j++)
65         {
66             if(val[i]==val[j])
67             {
68                 printf("%d\n",j);
69                 break;
70             }
71         }
72     }
73 }
74 int main()
75 {
76     init_build_weigh_solve();
77     return 0;
78 }

原文地址:https://www.cnblogs.com/Qin-Wei-Kai/p/10204381.html

时间: 2024-11-14 12:12:45

【树hs】[BJOI2015]树的同构的相关文章

[BZOJ4337][BJOI2015]树的同构(树的最小表示法)

4337: BJOI2015 树的同构 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1023  Solved: 436[Submit][Status][Discuss] Description 树是一种很常见的数据结构. 我们把N个点,N-1条边的连通无向图称为树. 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树. 对于两个树T1和T2,如果能够把树T1的所有点重新标号,使得树T1和树T2完全相 同,那么这两个树是同

4337. [BJOI2015]树的同构【树哈希】

Description 树是一种很常见的数据结构. 我们把N个点,N-1条边的连通无向图称为树. 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树. 对于两个树T1和T2,如果能够把树T1的所有点重新标号,使得树T1和树T2完全相 同,那么这两个树是同构的.也就是说,它们具有相同的形态. 现在,给你M个有根树,请你把它们按同构关系分成若干个等价类. Input 第一行,一个整数M. 接下来M行,每行包含若干个整数,表示一个树.第一个整数N表示点数.接下来N 个整数,依次

luogu P5043 【模板】树同构([BJOI2015]树的同构)

题面: 树是一种很常见的数据结构. 我们把N个点,N−1条边的连通无向图称为树. 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树. 对于两个树T1和T2,如果能够把树T1的所有点重新标号,使得树T1和树T2完全相同,那么这两个树是同构的.也就是说,它们具有相同的形态. 现在,给你M个有根树,请你把它们按同构关系分成若干个等价类. 无根树Hash... 以树的每一个节点为根,求出Hash值后,存入一个数组里,排序. 比对就像这样 for(int j=1;j<=i;j++

面试总结(数据库索引、B树、B+树)

1.  数据库系统维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法.这种数据结构,就是索引.索引的实现通常使用B树及其变种B+树. 创建索引可以大大提高系统的性能. 第一.通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性. 第二.可以大大加快数据的检索速度,这也是创建索引的最主要的原因. 第三.可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义. 第四.在使用分组和排序子句进行数据检索时,同样可以显著减

跳跃表,字典树(单词查找树,Trie树),后缀树,KMP算法,AC 自动机相关算法原理详细汇总

第一部分:跳跃表 本文将总结一种数据结构:跳跃表.前半部分跳跃表性质和操作的介绍直接摘自<让算法的效率跳起来--浅谈"跳跃表"的相关操作及其应用>上海市华东师范大学第二附属中学 魏冉.之后将附上跳跃表的源代码,以及本人对其的了解.难免有错误之处,希望指正,共同进步.谢谢. 跳跃表(Skip List)是1987年才诞生的一种崭新的数据结构,它在进行查找.插入.删除等操作时的期望时间复杂度均为O(logn),有着近乎替代平衡树的本领.而且最重要的一点,就是它的编程复杂度较同类

trie树(字典树)

1. trie树,又名字典树,顾名思义,它是可以用来作字符串查找的数据结构,它的查找效率比散列表还要高. trie树的建树: 比如有字符串"ab" ,"adb","adc"   可以建立字典树如图: 树的根节点head不存储信息,它有26个next指针,分别对应着字符a,b,c等.插入字符串ab时,next['a'-'a']即next[0]为空,这是申请一个结点放在next[0]的位置,插入字符串db时,next['d'-'a']即next[3]

B树、B+树、红黑树、AVL树比较

B树是为了提高磁盘或外部存储设备查找效率而产生的一种多路平衡查找树. B+树为B树的变形结构,用于大多数数据库或文件系统的存储而设计. B树相对于红黑树的区别 在大规模数据存储的时候,红黑树往往出现由于树的深度过大而造成磁盘IO读写过于频繁,进而导致效率低下的情况.为什么会出现这样的情况,我们知道要获取磁盘上数据,必须先通过磁盘移动臂移动到数据所在的柱面,然后找到指定盘面,接着旋转盘面找到数据所在的磁道,最后对数据进行读写.磁盘IO代价主要花费在查找所需的柱面上,树的深度过大会造成磁盘IO频繁读

B树、B-树、B+树、B*树

B树.B-树.B+树.B*树 B树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: B树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中: 否则,如果查询关键字比结点关键字小,就进入左儿子:如果比结点关键字大,就进入 右儿子:如果左儿子或右儿子的指针为空,则报告找不到相应的关键字: 如果B树的所有非叶子结点的左右子树的结点数目均保持差

从B树、B+树、B*树谈到R 树

第一节.B树.B+树.B*树 1.前言: 动态查找树主要有:二叉查找树(Binary Search Tree),平衡二叉查找树(Balanced Binary Search Tree),红黑树(Red-Black Tree ),B-tree/B+-tree/ B*-tree(B~Tree).前三者是典型的二叉查找树结构,其查找的时间复杂度O(log2N)与树的深度相关,那么降低树的深度自然会提高查找效率. 但是咱们有面对这样一个实际问题:就是大规模数据存储中,实现索引查询这样一个实际背景下,树节