4337: BJOI2015 树的同构

Description

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

Input

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

Output

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

Sample Input

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

Sample Output

1
1
3
1

HINT

【样例解释】 
编号为1, 2, 4 的树是同构的。编号为3 的树只与它自身同构。 
100% 的数据中,1 ≤ N, M ≤ 50。 
 
 
 
题意:
给出M棵树,编号1~M,对于每棵树,询问与其同构的树的最小编号。
 
 
题解:
关键就在于如何判断两棵树是否同构。
对于N个节点的无根树来说,枚举每个节点作为根,求最小表示法的序列。
 
最小表示法:
将子节点的最小表示序列排序(字符串字典序),把这些序列连接到一起,外面套一层小括号。
递归回根节点生成的序列就是该树最小表示法。
 
所以每棵树的最小表示法有N种。
想要知道两棵树a,b是否同构,只需用a的一种最小表示法和b的所有最小表示法来比较,如果有相同,两棵树就是同构的。
 
/*
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◇◆◆◆◇◇◇◇◇
◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◆◆◇◇◇◇◇◇◇◇◇◇◆◆◆◆◆◇◇◇◇◇
◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◆◆◇◇◇◇◇◇◇◇◇◇◆◆◇◆◆◇◇◇◇◇
◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇◇◇◆◇◇◇◆◇◇◇◇◇
◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◇◆◆◇◇◇◇◇◇◇◇◇◇◇◇◆◇◇◇◆◇◇◇◇◇
◇◇◇◇◇◇◇◆◇◇◇◇◇◇◇◇◇◇◇◇◆◆◆◇◆◇◇◇◇◇◇◇◇◇◇◆◇◇◇◆◇◇◇◇◇
◇◇◇◇◇◇◆◆◆◆◇◇◇◇◇◇◇◇◇◇◆◆◆◆◆◇◇◇◇◇◇◇◇◇◆◆◆◇◆◆◆◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<vector>
using namespace std;
int read(){
int xx=,ff=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')ff=-;ch=getchar();}
while(ch>=''&&ch<=''){xx=xx*+ch-'';ch=getchar();}
return xx*ff;
}
const int maxn=;
int T,N[maxn],lin[maxn],len;
struct edge{
int y,next;
}e[maxn<<];
inline void insert(int xx,int yy){
e[++len].next=lin[xx];
lin[xx]=len;
e[len].y=yy;
}
string H[maxn][maxn];
string temp[maxn];
int son[maxn][maxn],cnt[maxn];
bool mycmp(const int &xx,const int &yy)
{return temp[xx]<temp[yy];}
void dfs(int x,int fa){
cnt[x]=;
for(int i=lin[x];i;i=e[i].next)
if(e[i].y!=fa){
dfs(e[i].y,x);
son[x][++cnt[x]]=e[i].y;
}
sort(&son[x][],&son[x][cnt[x]+],mycmp);
temp[x]="(";
for(int i=;i<=cnt[x];i++)
temp[x]+=temp[son[x][i]];
temp[x]+=")";
}
bool check(int x,int y){
if(N[x]!=N[y])
return ;
for(int i=;i<=N[x];i++)
if(H[x][i]==H[y][])
return ;
return ;
}
int main(){
//freopen("in.txt","r",stdin);
T=read();
for(int i=;i<=T;i++){
N[i]=read();
memset(lin,,sizeof(lin));len=;
for(int j=;j<=N[i];j++){
int t=read();
if(t)
insert(j,t),insert(t,j);
}
for(int j=;j<=N[i];j++){
dfs(j,);
H[i][j]=temp[j];
}
}
for(int i=;i<=T;i++)
for(int j=;j<=i;j++)
if(check(i,j)){
printf("%d\n",j);
break;
}
/*for(int i=1;i<=T;i++){
for(int j=1;j<=N[i];j++)
cout<<H[i][j]<<endl;
cout<<endl;
}*/
return ;
}
 
 
 
 
 
 
 
 

bzoj 4337 树的同构的更多相关文章

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

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

  2. 4337: BJOI2015 树的同构

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

  3. Luogu 5043 【模板】树同构([BJOI2015]树的同构)

    BZOJ 4337 简单记录一种树哈希的方法:以$x$为根的子树的哈希值为$\sum_{y \in son(x)}f_y*base_i$,$f_y$表示以$y$为根的树的哈希值,其中$i$表示$f_y ...

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

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

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

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

  6. 【BZOJ4337】树的同构(树同构,哈希)

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

  7. 03-树1 树的同构 (C语言链表实现)

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h& ...

  8. PAT 03-树1 树的同构 (25分)

    给定两棵树T1和T2.如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是"同构"的.例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A.B.G的左右孩子互换后 ...

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

    数据结构实验之二叉树一:树的同构 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 给定两棵树 ...

随机推荐

  1. CSS 全局样式

    设置全局 CSS 样式:基本的 HTML 元素均可以通过 class 设置样式并得到增强效果:还有先进的栅格系统.

  2. mysql 存储过程批量删除重复数据

    表结构: LOAD DATA INFILE '/usr/local/phone_imsi_12' replace INTO TABLE tbl_imsi2number_new FIELDS TERMI ...

  3. ajax 简单学习

    客户端代码function login(type) { $.ajax({ type: "post", url: "logindo.aspx", data: { ...

  4. stark组件之显示页面搭建(四)

    页面搭建包括第一如何获取前端传过来的数据,第二如何在前端渲染出对应标签. 一.后台获取数据并进行处理 在路由系统中,每一个路由都对应着一个处理函数,如下所示: def wrapper(self, fu ...

  5. stm8l定时器中的ARPE

    • Auto-reload preload enabled (ARPE bit set in the TIM1_CR1 register). In this mode,when data is wri ...

  6. JQuery常用的案例

    1.给导航栏添加鼠标移上去的时候变换背景颜色的方法. $(function () { $(".nav li").mouseover(function () { $(this).cs ...

  7. [BZOJ1138][POI2009]Baj 最短回文路

    [BZOJ1138][POI2009]Baj 最短回文路 试题描述 N个点用M条有向边连接,每条边标有一个小写字母. 对于一个长度为D的顶点序列,回答每对相邻顶点Si到Si+1的最短回文路径. 如果没 ...

  8. msp430入门编程11

    msp430中C语言的模块化头文件及实现11 msp430中C语言的模块化头文件及库文件12 msp430入门学习 msp430入门编程

  9. poj 3233 Matrix Power Series 矩阵求和

    http://poj.org/problem?id=3233 题解 矩阵快速幂+二分等比数列求和 AC代码 #include <stdio.h> #include <math.h&g ...

  10. bzoj2212 Tree Rotations

    被BZOJ坑了一下午,原以为是我程序有问题一直WA,结果是我数组小了...为啥不给我RE!!! 线段树合并,对于逆序对而言,只能通过交换左右子树来达到,那么我们就可以想到对于一个结点而言,我们当然要取 ...