• BZOJ 4337: BJOI2015 树的同构 树hash


    4337: BJOI2015 树的同构

    题目连接:

    http://www.lydsy.com/JudgeOnline/problem.php?id=4337

    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。

    题意

    题解

    从树的重心开始hash,因为重心最多两个。

    然后找到树的最小表示就好了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 555;
    int f[maxn],son[maxn],n,mx;
    vector<int>E[maxn];
    string h[maxn],h2[maxn],ha[maxn];
    void getroot(int x,int fa)
    {
        son[x]=1,f[x]=0;
        for(int i=0;i<E[x].size();i++)
        {
            int p=E[x][i];
            if(p==fa)continue;
            getroot(p,x);
            son[x]+=son[p];
            f[x]=max(f[x],son[p]);
        }
        f[x]=max(f[x],n-son[x]);
        mx=max(f[x],mx);
    }
    void init()
    {
        for(int i=1;i<=n;i++)E[i].clear();
        mx=0;
        memset(f,0,sizeof(f));
        memset(son,0,sizeof(son));
    }
    void dfs(int x,int fa){
        h[x]="(";
        for(int i=0;i<E[x].size();i++){
            int v = E[x][i];
            if(v!=fa)dfs(v,x);
        }
        int now=0;
        for(int i=0;i<E[x].size();i++){
            int v = E[x][i];
            if(v!=fa)
                h2[now++]=h[v];
        }
        sort(h2,h2+now);
        for(int i=0;i<now;i++)
            h[x]+=h2[i];
        h[x]+=")";
    }
    string get()
    {
        scanf("%d",&n);
        init();
        for(int i=1;i<=n;i++){
            int x;scanf("%d",&x);
            if(x){
                E[x].push_back(i);
                E[i].push_back(x);
            }
        }
        getroot(1,0);
        string tmp = "";
        for(int i=1;i<=n;i++){
            if(f[i]==mx)
            {
                dfs(i,0);
                if(h[i]>tmp)tmp=h[i];
            }
        }
        return tmp;
    }
    int main()
    {
        int q;scanf("%d",&q);
        for(int i=1;i<=q;i++)
            ha[i]=get();
        for(int i=1;i<=q;i++){
            for(int j=1;j<=i;j++){
                if(ha[i]==ha[j]){
                    cout<<j<<endl;
                    break;
                }
            }
        }
    }
  • 相关阅读:
    Map和Set
    js基本语法入门
    js中变量的作用域,let,const详解
    循环结构
    方法
    只有分享才能一起进步
    培训随笔
    得食相呼,义也
    Wall.e
    《国学之大智慧》观感
  • 原文地址:https://www.cnblogs.com/qscqesze/p/6042436.html
Copyright © 2020-2023  润新知