bzoj4337树的同构

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

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

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

对于两个树T1和T2,如果能够把树T1的所有点重新标号,使得树T1和树T2完全相

同,那么这两个树是同构的。也就是说,它们具有相同的形态。

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

树哈希模板题。

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 52
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int tt,n,head[N],tot,num[N];
ll disso[N][N],ha[N];
const int base=19260817;
struct node{
    int n,to;
}e[N<<1];
inline void add(int u,int v){
    e[++tot].n=head[u];
    e[tot].to=v;
    head[u]=tot;
}
void dfs(int u,int fa,int deep){
    int ji[N],top=0;
    ji[++top]=deep;
    for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
        int v=e[i].to;
        dfs(v,u,deep+1);
        ji[++top]=ha[v];
    }
    ha[u]=0;
    sort(ji+1,ji+top+1);
    for(int i=1;i<=top;++i)ha[u]=(ha[u]*base+ji[i])%mod;
}
int main(){
    scanf("%d",&tt);
    for(int i=1;i<=tt;++i){
        scanf("%d",&n);num[i]=n;
        memset(head,0,sizeof(head));tot=0;
        int ba;
        for(int j=1;j<=n;++j){
            scanf("%d",&ba);
            if(ba)add(ba,j),add(j,ba);
        }
        for(int j=1;j<=n;++j){
            dfs(j,0,1);disso[i][j]=ha[j];
        }
        sort(disso[i]+1,disso[i]+n+1);
        for(int j=1;j<=i;++j){
            if(num[j]!=num[i])continue;bool tag=0;
            for(int k=1;k<=n;++k)if(disso[i][k]!=disso[j][k])tag=1;
            if(!tag){
                printf("%d\n",j);
                break;
            }
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/ZH-comld/p/9898528.html

时间: 2024-10-31 17:08:13

bzoj4337树的同构的相关文章

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

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

数据结构实验之二叉树一:树的同构 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 给定两棵树T1和T2.如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是"同构"的.例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A.B.G的左右孩子互换后,就得到另外一棵树.而图2就不是同构的. 图1 图2 现给定两棵树,请你判断它们是否是同构的. Input 输入数据包含

03-树1 树的同构

给定两棵树T1和T2.如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的.例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A.B.G的左右孩子互换后,就得到另外一棵树.而图2就不是同构的. 图1 图2 现给定两棵树,请你判断它们是否是同构的. 输入格式: 输入给出2棵二叉树树的信息.对于每棵树,首先在一行中给出一个非负整数NN (\le 10≤10),即该树的结点数(此时假设结点从0到N-1N−1编号):随后NN行,第ii行对应编号第ii个结点,给出该结点中存储的

5-3 树的同构 (25分)

5-3 树的同构   (25分) 给定两棵树T1和T2.如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是"同构"的.例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A.B.G的左右孩子互换后,就得到另外一棵树.而图2就不是同构的. 图1 图2 现给定两棵树,请你判断它们是否是同构的. 输入格式: 输入给出2棵二叉树树的信息.对于每棵树,首先在一行中给出一个非负整数NN (\le 10≤10),即该树的结点数(此时假设结点从0到N-1N?1编号):随后NN行,第i

ZOJ--3602--Count the Trees【DFS+Hash】树的同构

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3602 题意:给出一棵有n个节点的二叉树和一棵有m个节点的二叉树,给出每个节点的左右子树信息,问这两棵树有几个相同的子树. 思路:树的同构,比赛时没想法,赛后看的别人的解题报告.实际上是给每个节点的左右子树一个哈希值,不用像字符串哈希那么麻烦,直接给每个子树一个数字标记就行了,用map映射每个节点的左子树和右子树信息对应一个标记值,用DFS给两棵树的每个节点都赋一个哈

BZOJ 4337 树的同构

很明显,这应该是一道模版题(因为我很快就在一本书上找到了这道题的模版),不过令我比较奇怪的大概是有根树和无根树的概念,以及在这道题目中根有卵用吗? (看来树这一块的知识还是要补一下). 树的同构很明显应该是用hash来判断的,当然了,不同的人设计的hash函数不同了.这道题正确的应该是要在树的重心上面跑这道题的模版,(如果你要问我树的重心是啥,我只能跟你说,如果我知道的话,下面这份代码就不会把几乎所有的点都跑一次了,但是由于N<=50,M <= 50 很明显这样跑完还是很快的,事实证明也只跑了

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

1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <stdbool.h> 5 6 typedef char ElemType; 7 8 typedef struct BinTree 9 { 10 ElemType data; 11 struct BinTree *left; 12 struct BinTree *right; 13 }BinTree; 14

PTA 树的同构(25 分)

7-1 树的同构(25 分) 给定两棵树T1和T2.如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是"同构"的.例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A.B.G的左右孩子互换后,就得到另外一棵树.而图2就不是同构的. 图1 图2 现给定两棵树,请你判断它们是否是同构的. 输入格式: 输入给出2棵二叉树树的信息.对于每棵树,首先在一行中给出一个非负整数N (≤10),即该树的结点数(此时假设结点从0到N?1编号):随后N行,第i行对应编号第i个结点,给出

树的同构

给定两棵树T1和T2.如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是"同构"的.例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A.B.G的左右孩子互换后,就得到另外一棵树.而图2就不是同构的. 图1 图2 现给定两棵树,请你判断它们是否是同构的. 输入格式: 输入给出2棵二叉树树的信息.对于每棵树,首先在一行中给出一个非负整数N (≤),即该树的结点数(此时假设结点从0到N?1编号):随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母.其