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

题面:

  树是一种很常见的数据结构。

  我们把N个点,N−1条边的连通无向图称为树。

  若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树。

  对于两个树T1和T2,如果能够把树T1的所有点重新标号,使得树T1和树T2完全相同,那么这两个树是同构的。也就是说,它们具有相同的形态。

  现在,给你M个有根树,请你把它们按同构关系分成若干个等价类。

无根树Hash。。。

以树的每一个节点为根,求出Hash值后,存入一个数组里,排序。

比对就像这样

  

for(int j=1;j<=i;j++){
    bool flag=0;
    for(int k=1;k<=n;k++) if(H[i][k]!=H[j][k]) flag=1;
    if(!flag) {printf("%d\n",j);break;}
    } 

至于怎样求以一个节点为根时树的Hash值,

先把它的子节点的Hash值存入一个vector里,排序,然后就像字符串Hash一样,求就完事了,叶子节点返回 1 。

ll dfs(int x,int fa){
    ll res=1;vector<ll> v;
    for(int i=Head[x];i;i=nex[i]){
        int y=ver[i];if(y==fa) continue;
        v.push_back(dfs(y,x));
    }
    sort(v.begin(),v.end());
    for(unsigned int i=0;i<v.size();i++) res=(res*P+v[i])%mod;
    return res%mod;
}

然后就能切掉了啦。

一开始我找树的重心,然后像上面那样求以重心为根节点的Hash值,由于可能有2个重心,取较小值即可。然而只有30pts。QAQ。。。。。。

原文地址:https://www.cnblogs.com/SyhAKIOI/p/11676862.html

时间: 2024-10-19 13:45:28

luogu P5043 【模板】树同构([BJOI2015]树的同构)的相关文章

[luogu P3384] [模板]树链剖分

[luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和 操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z 操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和 输入输出格式 输入格式: 第一行包含4个正整数

[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完全相 同,那么这两个树是同

luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)

luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目 #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #include<cstring> #include<iomanip> #include<algorithm> #include<ctime> #include<queue> #inc

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

P3377 【模板】左偏树(可并堆)

P3377 [模板]左偏树(可并堆) 题目描述 如题,一开始有N个小根堆,每个堆包含且仅包含一个数.接下来需要支持两种操作: 操作1: 1 x y 将第x个数和第y个数所在的小根堆合并(若第x或第y个数已经被删除或第x和第y个数在用一个堆内,则无视此操作) 操作2: 2 x 输出第x个数所在的堆最小数,并将其删除(若第x个数已经被删除,则输出-1并无视删除操作) 输入输出格式 输入格式: 第一行包含两个正整数N.M,分别表示一开始小根堆的个数和接下来操作的个数. 第二行包含N个正整数,其中第i个

吊打线段树的超级树状数组

你是否讨厌线段树那冗长的代码?你是否还在因为线段树的难调试而满头♂dark汗?那么,请不要错过!超级树状数组特价!只要998,只要998! ##¥……#……¥%……&%¥……ER#%$#$#^T%$^$% 超级树状数组,其实是一种能够支持区间修改和区间查询的树状数组,和线段树相比,它的常数极小,不需要太多空间,代码量也少了很多(简直吊打线段树) 1.树状数组 既然是超级树状数组,那么就需要一个树状数组作为基础了.但是在真正实现时,只用到了lowbit()函数(所以说lowbit是树状数组的核心啊

[可持久化线段树(主席树)]

主席树 抛出问题 如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输出格式 输入格式: 第一行包含两个正整数N.M,分别表示序列的长度和查询的个数. 第二行包含N个整数,表示这个序列各项的数字. 接下来M行每行包含三个整数l, r, kl,r,k , 表示查询区间[l, r][l,r]内的第k小值. 输出格式: 输出包含k行,每行1个整数,依次表示每一次查询的结果 解决问题 主席树(可持久化线段树)法 于是针对这个问题,新的数据结构诞生了,也就是主席树. 主席树本名

[SDOI2016]游戏 树剖+李超树

链接 https://www.luogu.org/problemnew/show/P4069 思路 树剖+超哥线段树 我已经自毙了,自闭了!!!! 代码 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define ll long long using namespace std; const ll N=400007LL; const ll inf=