zoukankan      html  css  js  c++  java
  • BJOI2015-数的同构(树的哈希)

    树是一种很常见的数据结构。 我们把N个点,N-1条边的连通无向图称为树。 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树。 对于两个树T1和T2,如果能够把树T1的所有点重新标号,使得树T1和树T2完全相 同,那么这两个树是同构的。也就是说,它们具有相同的形态。 现在,给你M个有根树,请你把它们按同构关系分成若干个等价类。
    输入
    第一行,一个整数M。 接下来M行,每行包含若干个整数,表示一个树。第一个整数N表示点数。接下来N 个整数,依次表示编号为1到N的每个点的父亲结点的编号。根节点父亲结点编号为0。
    输出
    输出M行,每行一个整数,表示与每个树同构的树的最小编号。
    样例输入
    4
    4 0 1 1 2
    4 2 0 2 3
    4 0 1 1 1
    4 0 1 2 3
    样例输出
    1
    1
    3
    1
    提示
    【样例解释】
    编号为1, 2, 4 的树是同构的。编号为3 的树只与它自身同构。
    100% 的数据中,1 ≤ N, M ≤ 50。

    很简单的hash

    直接暴力就可以了

    只要将每一颗子树的hash值排个序,逐一比较就可以了

    那我们来考虑点别的

    如果n,m大小是1e5呢?

    那也不难,

    我们只需要找到每个树的中心

    从重心来hash就可以了

    #include<bits/stdc++.h>
    #define uint unsigned int 
    using namespace std;
    inline int read(){
        char ch=getchar();
        int res=0;
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
        return res;
    }
    int p[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229};
    int adj[200],nxt[200],to[200],m,n,d[200],cnt;
    uint hash[100][100];
    inline void addedge(int u,int v)
    {
        nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
        nxt[++cnt]=adj[v],adj[v]=cnt,to[cnt]=u;
    }
    inline uint hashin(int u,int fa)
    {
        int nu=0;
        uint a[55],k=1;
        for(int i=adj[u];i;i=nxt[i])
        {
            if(to[i]!=fa) a[++nu]=hashin(to[i],u);
        }
        sort(a+1,a+nu+1);
        for(int i=1;i<=nu;i++)
        {
            k=k*409+a[i]*p[i];
        }
        return k;
    }
    int main(){
        m=read();
        for(int i=1;i<=m;i++)
        {
            cnt=0;
            memset(adj,0,sizeof(adj));
            memset(to,0,sizeof(adj));
            memset(nxt,0,sizeof(adj));
            d[i]=read();
            int x;
            for(int j=1;j<=d[i];j++)
            {
                x=read();
                if(x)
                addedge(x,j);
            }
            for(int j=1;j<=d[i];j++)
            {
                hash[i][j]=hashin(j,0);
            }
            sort(hash[i]+1,hash[i]+d[i]+1);
            for(int j=1;j<=i;j++)
            {
                if(d[i]==d[j])
                {
                    bool iv=0;
                    for(int k=1;k<=d[i];k++) if(hash[i][k]!=hash[j][k]) {iv=1;break;}
                    if(!iv) {cout<<j<<'
    ';break;}
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    pom.xml 报错
    微信支付,提示当前页面URL未注册
    echarts + highcharts 柱状图
    二维码生成
    Eclipse
    SQLServer 安装及配置
    模板引擎doT.js用法详解
    SQL Server 笔记
    Flex 弹性盒模型
    查看Linux是Redhat 还是centos 还是...
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366495.html
Copyright © 2011-2022 走看看