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=0,ff=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')ff=-1;ch=getchar();}while(ch>='0'&&ch<='9'){xx=xx*10+ch-'0';ch=getchar();}return xx*ff;
}
const int maxn=55;
int T,N[maxn],lin[maxn],len;
struct edge{int y,next;
}e[maxn<<1];
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]=0;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][1],&son[x][cnt[x]+1],mycmp);temp[x]="(";for(int i=1;i<=cnt[x];i++)temp[x]+=temp[son[x][i]];temp[x]+=")";
}
bool check(int x,int y){if(N[x]!=N[y])return 0;for(int i=1;i<=N[x];i++)if(H[x][i]==H[y][1])return 1;return 0;
}
int main(){//freopen("in.txt","r",stdin);T=read();for(int i=1;i<=T;i++){N[i]=read();memset(lin,0,sizeof(lin));len=0;for(int j=1;j<=N[i];j++){int t=read();if(t)insert(j,t),insert(t,j);}for(int j=1;j<=N[i];j++){dfs(j,0);H[i][j]=temp[j];}}for(int i=1;i<=T;i++)for(int j=1;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 0;
}

View Code

转载于:https://www.cnblogs.com/lzhAFO/p/8886512.html

bzoj 4337 树的同构相关推荐

  1. 无根树的同构:Hash最小表示法(bzoj 4337: BJOI2015 树的同构)

    这里的同构是指: 对于两棵树A, B,如果能通过重新标号使得两棵树完全相同,则称树A和B同构 Hash最小表示法步骤: ①暴力每个节点为根 ②对于当前根x,对树进行DFS ③DFS时对每个节点维护一个 ...

  2. 【BZOJ - 4337】BJOI2015 树的同构(树哈希)

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

  3. [树hash]BZOJ 4337——BJOI2015 树的同构

    题目梗概 对于两个树T1和T2,如果能够把树T1的所有点重新标号,使得树T1和树T2完全相 同,那么这两个树是同构的. 有M个有根树,请你把它们按同构关系分成若干个等价类. 解题思路 第一次写树has ...

  4. 4337: BJOI2015 树的同构

    4337: BJOI2015 树的同构 Time Limit: 10 Sec   Memory Limit: 256 MB Submit: 171   Solved: 81 [ Submit][ St ...

  5. [BJOI2015] 树的同构

    4337: BJOI2015 树的同构 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 1092  Solved: 460 [Submit][Stat ...

  6. 树根c语言,03-树1 树的同构 (C语言链表实现)

    #include #include #include #include typedef char ElemType; typedef struct BinTree { ElemType data; s ...

  7. [BJOI2015]树的同构

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

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

    题目地址 https://pta.patest.cn/pta/test/15/exam/4/question/711 5-3 树的同构   (25分) 给定两棵树T1和T2.如果T1可以通过若干次左右 ...

  9. 树的同构(c语言静态链表实现)

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

最新文章

  1. 基于GPUImage的美颜BeautifyFace详细注释
  2. GetLastError()函数返回值及含义
  3. AirPrint: 无交互的后台打印实现(Print without UI,iOS8+)
  4. interactive_timeout和wait_timeout之间的区别
  5. 【整理】Spring 常用注解!千万不要错过!
  6. php rewrite url_PHP实现url重写和.htaccess
  7. MySQL数据库的回滚失败(JAVA)
  8. 复习:稀疏链表的十字链表
  9. 一款优秀的前端JS框架—AngularJS
  10. Source Insight 中查看日文注释
  11. SDN、NFV:一枝独秀不是春
  12. vivo x6plus支持html,vivo x6plus手机USB驱动
  13. Android6.0之AMS如何启动app中篇之Task的管理
  14. C++写的12306抢票软件
  15. Windows任务计划定时运行程序的配置方法
  16. Agth 辅助工具(GAL用agth进行自动翻译工具)
  17. ITIL入门 ITSM入门 事件入门 事件管理入门
  18. Longhorn云原生文件存储
  19. 详解 Python 中的 filter() 函数
  20. 亚马逊入驻商用户画像分析

热门文章

  1. 计算机网络的非性能特征PPT,计算机网络概述课件课件.ppt
  2. php observer,php设计模式 Observer (观察者模式)
  3. MYSQL中的SELECT查询时进行运算
  4. Java Integer.compareTo()比较大小
  5. java读文件指定行开始到文件的最后
  6. @Autowired 与@Resource的区别
  7. BIM 360 Docs API在操作欧洲数据中心内容的一些调整
  8. 使用VS2012遇到的问题
  9. vbox里面的Ubuntu虚拟机与主机win7之间设置共享文件夹
  10. 【maven详解-插件】maven插件学习之maven-source-plugin