题解【[BJOI2015]树的同构】
切了省选题+紫题,来写个题解
这题其实挺水,才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]树的同构】的更多相关文章
- BZOJ 4337: BJOI2015 树的同构 树hash
4337: BJOI2015 树的同构 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4337 Description 树是一种很常见的数 ...
- bzoj4337: BJOI2015 树的同构 树哈希判同构
题目链接 bzoj4337: BJOI2015 树的同构 题解 树哈希的一种方法 对于每各节点的哈希值为hash[x] = hash[sonk[x]] * p[k]; p为素数表 代码 #includ ...
- 【BZOJ4337】BJOI2015 树的同构 括号序列
[BZOJ4337]BJOI2015 树的同构 Description 树是一种很常见的数据结构. 我们把N个点,N-1条边的连通无向图称为树. 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱 ...
- 4337: BJOI2015 树的同构
题解: 树的同构的判定 有根树从根开始进行树hash 先把儿子的f进行排序 $f[i]=\sum_{j=1}^{k} { f[j]*prime[j]} +num[i]$(我没有仔细想这样是不是树是唯一 ...
- [BZOJ4337][BJOI2015]树的同构(树的最小表示法)
4337: BJOI2015 树的同构 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1023 Solved: 436[Submit][Status ...
- BZOJ4337:[BJOI2015]树的同构——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4337 树是一种很常见的数据结构. 我们把N个点,N-1条边的连通无向图称为树. 若将某个点作为根, ...
- [BJOI2015]树的同构
嘟嘟嘟 判断树的同构的方法就是树上哈希. 如果树是一棵有根树,那么只要从根节点出发dfs,每一个节点的哈希值等于按传统方式算出来的子树的哈希值的结果.需要注意的是,算完子树的哈希值后要先排序再加起来, ...
- BZOJ4337:[BJOI2015]树的同构(树hash)
Description 树是一种很常见的数据结构. 我们把N个点,N-1条边的连通无向图称为树. 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树. 对于两个树T1和T2,如 ...
- 题解 P5043 【【模板】树同构([BJOI2015]树的同构)】
进入正题 题意:将所有树结构相同的树归类. 思路 嗯,这道题让我们把树的结构归类,自然而然就想到了哈希,我们对这整颗树哈希一遍.然后判同构就十分之简单了.只需要找哈希值一样的树就可以了. 其实真得很简 ...
随机推荐
- 吴裕雄--天生自然C++语言学习笔记:C++ 基本的输入输出
C++ 的 I/O 发生在流中,流是字节序列.如果字节流是从设备(如键盘.磁盘驱动器.网络连接等)流向内存,这叫做输入操作.如果字节流是从内存流向设备(如显示屏.打印机.磁盘驱动器.网络连接等),这叫 ...
- NumPy 数组切片
章节 Numpy 介绍 Numpy 安装 NumPy ndarray NumPy 数据类型 NumPy 数组创建 NumPy 基于已有数据创建数组 NumPy 基于数值区间创建数组 NumPy 数组切 ...
- 大数据之虚拟机配置和环境准备及hadoop集群搭建
一.VMnet1和VMnet8路由器 VMware-workstation软件选择默认安装时,会自动创建VMnet1和VMnet8路由器设备.(安装失败使用CCleaner清理vm软件) VMnet1 ...
- flutter文本简单实现
import 'package:flutter/material.dart'; import 'package:flustars/flustars.dart'; import 'package:fl_ ...
- windows driver 获取文件属性
OBJECT_ATTRIBUTES oa; FILE_NETWORK_OPEN_INFORMATION fnoi; UNICODE_STRING strPath = RTL_CONSTANT_STRI ...
- C语言:大数求和
点击获取题目 1410: [蓝桥杯]高精度加法 时间限制: 1 Sec 内存限制: 256 MB提交: 28 解决: 20[状态] [提交] [命题人:外部导入] 题目描述 输入两个整数a和b,输 ...
- jQuery网页定时弹出广告
1.下载jQuery,并导入:https://blog.csdn.net/weixin_44718300/article/details/88746796 2.代码实现: <!DOCTYPE h ...
- 对input type=file 修改样式
效果图先给: 在html中涉及到文件选择的问题,文件选择使用 input(class="filter_input form-control" type="file) 但是 ...
- 201771010123汪慧和《面向对象程序设计Java》第十七周实验总结
一.理论部分 1.多线程并发执行中的问题 ◆多个线程相对执行的顺序是不确定的. ◆线程执行顺序的不确定性会产生执行结果的不确定性. ◆在多线程对共享数据操作时常常会产生这种不确定性. 2.线程的同步 ...
- 可重入排他锁ReentrantLock源码浅析
1.引子 "ReentrantLock"单词中的“Reentrant”就是“重入”的意思,正如其名,ReentrantLock是一个支持重入的排他锁,即同一个线程中可以多次获得同步 ...