切了省选题+紫题,来写个题解

这题其实挺水,才120行代码

该题写了我一天(上午1.5h,晚上10min = 一天)

hash,对于节点A,$$hashval[A] = {hashval[i]\times2333^{num} | i \in son[A] }$$ , 并且hashval[i]大于任何在他前面加的数,num为目前加到第几个

写成代码就是

function Hash(int n){
vector V ;
for_each(i in son[n]) do
HV[i] = Hash(i) ;
V.pushback(HV[i]) ;
V.sort()
for_each(i in V)
HV[n] = HV[n]*2333+HV[i] ;
return HV[n]*2333+1002 ;
//HV[i]初值为1
}

那么对于树中的每个节点做一遍Hash,时间复杂度为$$O(N \times (N+NlogN+N))$$

所以总的的时间复杂度为$$O(M \times N \times NlogN) == O(N^3logN)$$

说人话:$$O(\text{能过})$$

\[\]

\[\]

Talk is free , show me the code

#include<iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std ;
inline void read(int &x) {
char ch=getchar();
int s=0,f=1;
while (!(ch>='0'&&ch<='9')) {
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9') {
s=(s<<3)+(s<<1)+ch-'0';
ch=getchar();
}
x=s*f;
}
class TREE{
private:
vector<int> son[55] ;
int hashval[55] ;
int H[55] ;
bool inq[55] ;
int size[55] ;
int root ;
int n ;
int check(vector<int> N){
int S = N.size() ;
for(int j:N) {
if(inq[j]) --S ;
}
return S ;
}
public:
//这个MIAOMIAOMIAO函数就是Hash啦喵~
int MIAOMIAOMIAO(int n,int f){
inq[n] = true ;
vector<int> V ;
for(const int & i : son[n]){
if(i==f) continue ;
//cout<<"dfs in dot "<<i<<endl ;
hashval[i] = MIAOMIAOMIAO(i,n) ;
//cout<<"HashVal["<<i<<"] = "<<hashval[i]<<endl ;
V.push_back(hashval[i]) ;
//cout<<"HashVal["<<n<<"] = "<<hashval[n]<<endl ;
}
sort(V.begin(),V.end()) ;
for(const int& i : V)
hashval[n] = hashval[n]*2333 + i ;
//hashval[n] = 2333*hashval[n] + 1001 ;
return hashval[n]*2333+1002 ;
}
void getsize(int n,int f){
inq[n] = true ;
if(!check(son[n])) size[n] = 1 ;
for(int i:son[n]){
if(i!=f) getsize(i,n) ;
size[n] += size[i] ;
}
}
bool comp(const int& a,const int& b){
return a>b ;
}
int sZ() {return this->n ;}
void init(){
read(n) ;
for(int i=1;i<=n;++i){
int x ;
read(x) ;
if(x==0) { root=i ; continue ; }
son[x].push_back(i) , son[i].push_back(x) ;
}
//cout<<"Root = "<<root<<endl ;
getsize(root,root) ;
memset(inq,0,sizeof(inq)) ;
for(int i=1;i<=n;++i){
sort(son[i].begin() , son[i].end() , [this](int a, int b) -> bool { return size[a] < size[b]; }) ;
}
for(int j=1;j<=n;++j) hashval[j] = 1 ;
for(int i=1;i<=n;++i){
MIAOMIAOMIAO(i,i) ;
H[i] = hashval[i] ;
memset(inq,0,sizeof(inq)) ;
for(int j=1;j<=n;++j) hashval[j] = 1 ;
}
//for(int i=1;i<=n;++i) cout<<H[i]<<" ";
//cout<<endl ;
}
int gethashval(int DI){
return H[DI] ;
}
} ;
TREE Index[55] ;
int m ;
int HVL[55] ;
int ans[55][55] ;
int main(){
read(m) ;
for(int i=1;i<=m;++i){
//cout<<"TREE "<<i<<endl ;
Index[i].init() ;
HVL[i] = i ;
int n = Index[i].sZ() ;
for(int j=1;j<=n;++j){
ans[i][j] = Index[i].gethashval(j) ;
}
sort(ans[i]+1,ans[i]+n+1) ;
for(int j=1;j<=i;++j){
int k = 0 ;
while(k<=n)
if(ans[i][++k]!=ans[j][k])
break ;
if(k>n) { HVL[i] = j ; break ; }
}
}
for(int i=1;i<=m;++i) {
printf("%d\n",HVL[i]) ;
}
}

Oh对了

本代码使用C++11标准并对每棵树封装

提交时注意~~(我不会告诉你我因为这个WA了一次喵~

还有说下那个for

for(const int& i : vector1) -> 对于每个vector1中的元素i,按vector1中的存放顺序访问

所以这个写起来省力~~(我不会告诉你还可以写for(auto& i:vector1)但是我忘了写喵~

题解【[BJOI2015]树的同构】的更多相关文章

  1. BZOJ 4337: BJOI2015 树的同构 树hash

    4337: BJOI2015 树的同构 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4337 Description 树是一种很常见的数 ...

  2. bzoj4337: BJOI2015 树的同构 树哈希判同构

    题目链接 bzoj4337: BJOI2015 树的同构 题解 树哈希的一种方法 对于每各节点的哈希值为hash[x] = hash[sonk[x]] * p[k]; p为素数表 代码 #includ ...

  3. 【BZOJ4337】BJOI2015 树的同构 括号序列

    [BZOJ4337]BJOI2015 树的同构 Description 树是一种很常见的数据结构. 我们把N个点,N-1条边的连通无向图称为树. 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱 ...

  4. 4337: BJOI2015 树的同构

    题解: 树的同构的判定 有根树从根开始进行树hash 先把儿子的f进行排序 $f[i]=\sum_{j=1}^{k} { f[j]*prime[j]} +num[i]$(我没有仔细想这样是不是树是唯一 ...

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

    4337: BJOI2015 树的同构 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1023  Solved: 436[Submit][Status ...

  6. BZOJ4337:[BJOI2015]树的同构——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4337 树是一种很常见的数据结构. 我们把N个点,N-1条边的连通无向图称为树. 若将某个点作为根, ...

  7. [BJOI2015]树的同构

    嘟嘟嘟 判断树的同构的方法就是树上哈希. 如果树是一棵有根树,那么只要从根节点出发dfs,每一个节点的哈希值等于按传统方式算出来的子树的哈希值的结果.需要注意的是,算完子树的哈希值后要先排序再加起来, ...

  8. BZOJ4337:[BJOI2015]树的同构(树hash)

    Description 树是一种很常见的数据结构. 我们把N个点,N-1条边的连通无向图称为树. 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树. 对于两个树T1和T2,如 ...

  9. 题解 P5043 【【模板】树同构([BJOI2015]树的同构)】

    进入正题 题意:将所有树结构相同的树归类. 思路 嗯,这道题让我们把树的结构归类,自然而然就想到了哈希,我们对这整颗树哈希一遍.然后判同构就十分之简单了.只需要找哈希值一样的树就可以了. 其实真得很简 ...

随机推荐

  1. mysql视图使用方法

    1.为什么要使用视图 对于复杂的查询,往往是有多个数据表进行关联查询而得到,而这种语句往往比较复杂,也可能非常频繁的使用.比如: select 字段一,字段二.字段三, from 数据表1 join ...

  2. 解决Tomcat在idea控制台乱码问题

    解决Tomcat乱码问题 打开Tomcat安装目录:apache-tomcat-9.0.14-windows-x64/conf/logging.properties 大概在50多行注释这一句#java ...

  3. Windows操作系统安装JDK环境

    Windows操作系统安装JDK环境 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一. Java常见的术语 1>.什么是JVM  只要在需要运行Java应用程序的操作系统上 ...

  4. UVA - 12627 Erratic Expansion(奇怪的气球膨胀)(递归)

    题意:问k小时后,第A~B行一共有多少个红气球. 分析:观察图可发现,k小时后,图中最下面cur行的红气球个数满足下式: (1)当cur <= POW[k - 1]时, dfs(k, cur) ...

  5. [题解] LuoguP4841 [集训队作业2013]城市规划

    Description 求\(n\)个点无重边.无自环.带标号的无向联通图个数,对\(1004535809\)(\(479 \times 2^{21} + 1\))取模.\(n \le 130000\ ...

  6. 关于indexOf的用法

     var fullTaskName = this.form.taskName;       var index=fullTaskName.lastIndexOf("-");     ...

  7. ansible 文本多行替换实例

    将<level='info'> 等全部替换为<level='ERROR'> - name: Before Ansible 2.3, option 'dest', 'destfi ...

  8. MyBatis:配置解析

    配置解析 核心配置文件 mybatis-config.xml 系统核心配置文件 MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息. 能配置的内容如下: configur ...

  9. js 数据

    非0数字值 都是true  0和NaN 都是false 任何对象   都是true  null       都是false undefined 不适用 详情

  10. JZOJ-2019-11-5 B组

    T1 给出一二维01矩阵\(f_{i,j}\), 定义点\((x_a, y_a), (x_b, y_b)\)的「距离」为\(max\{|x_a-x_b|, |y_a-y_b|\}\) 求出一矩阵\(w ...