BZOJ4337 BJOI2015 树的同构

  构造一个靠谱点的树哈希函数,每个树以每个点都为根算一次哈希值,然后归类一下有相同哈希值的树就行了。

  代码

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define nc() getchar()
 4 #define N 500100
 5 int dp,pre[N],p[N],ans[N],tt[N],n,i,m[N],a,j,k;
 6 long long q,hash[N],s[N],v[N];
 7 void link(int x,int y)
 8 {
 9     dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;
10 }
11 void root(int x,int fa)
12 {
13     int i=p[x];
14     long long ans=1;
15     s[x]=1;
16     while (i)
17     {
18         if (tt[i]!=fa)
19         {
20             root(tt[i],x);
21             long long tmp=v[tt[i]]+131;
22             s[x]=s[x]+s[tt[i]];
23             v[x]=v[x]+tmp;
24         }
25         i=pre[i];
26     }
27     v[x]=v[x]*s[x]%1000000007;
28 }
29 int main()
30 {
31     scanf("%d",&n);
32     for (i=1;i<=n;i++)
33     {
34         scanf("%d",&m[i]);
35         dp=0;
36         for (j=1;j<=m[i];j++) p[j]=0;
37         for (j=1;j<=m[i];j++)
38         {
39             scanf("%d",&a);
40             if (a)
41             {
42                 link(a,j);
43                 link(j,a);
44             }
45         }
46
47         for (j=1;j<=m[i];j++)
48         {
49             for (k=1;k<=m[i];k++)
50             s[k]=0,v[k]=0;
51             root(j,0);q=v[j];
52             for (k=1;k<i;k++)
53             if ((m[k]==m[i])&&(hash[k]==q))
54             {
55                 ans[i]=k;break;
56             }
57         }
58         if (ans[i]==0) ans[i]=i,hash[i]=q;
59
60     }
61     for (i=1;i<=n;i++)
62     printf("%d\n",ans[i]);
63 }
时间: 2024-10-14 11:24:26

BZOJ4337 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 个整数,依次

【树hs】[BJOI2015]树的同构

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

[BJOI2015]树的同构

介于这道题没大佬发重心的写法,我就来凑个热闹 前置知识 一.树的重心 定义如下:删掉某节点\(i\)后,若剩余\(k\)个连通分量,那么定义\(d(i)\)为这些连通分量中节点数的最大值.所谓重心,就是使得\(d(i)\)最小的节点\(i\). 定理:重心最多有两个 证明:比较感性的理解:一个重心代表一种最优均分的方案,最坏的情况就是左右为难,两个划分同样优 求法: //size[x]为x子树大小 //maxl为最后min{d(i)} inline void DFS(re int x,re in

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

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

[BJOI2015]树的同构 &amp;&amp; 树哈希教程

题目链接 有根树的哈希 离散数学中对树哈希的描述在这里.大家可以看看. 判断有根树是否同构,可以考虑将有根树编码.而编码过程中,要求保留树形态的特征,同时忽略子树顺序的不同.先来看一看这个方法: 不妨令一棵树的编码是个字符串\(T\). 对于一个点\(u\),先求出\(u\)所有\(son_u\)的编码\(f_{son_u}\),然后将这些编码按字典序从小到大排序得到\(g_{1\cdots k}\).那么\(f_u="0"+\sum\limits g_i+"1"\

bzoj4337树的同构

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

SDUT 3340 数据结构实验之二叉树一:树的同构

数据结构实验之二叉树一:树的同构 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 给定两棵树T1和T2.如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是"同构"的.例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A.B.G的左右孩子互换后,就得到另外一棵树.而图2就不是同构的. 图1 图2 现给定两棵树,请你判断它们是否是同构的. Input 输入数据包含

03-树1 树的同构

给定两棵树T1和T2.如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的.例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A.B.G的左右孩子互换后,就得到另外一棵树.而图2就不是同构的. 图1 图2 现给定两棵树,请你判断它们是否是同构的. 输入格式: 输入给出2棵二叉树树的信息.对于每棵树,首先在一行中给出一个非负整数NN (\le 10≤10),即该树的结点数(此时假设结点从0到N-1N−1编号):随后NN行,第ii行对应编号第ii个结点,给出该结点中存储的