zoukankan      html  css  js  c++  java
  • 刷题总结——树的同构(bzoj4337 树上hash)

    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解决树的同构问题的模板题···

    先说如何进行树上hash,设f[i]为以i为节点的hash值,则

           f[i]=sigma(f[j]*prime[j])  j为son[i]

    其中prime为预处理出来的素数表···注意f[j]需要进行排序····

    然后对于两颗待判定的树,将两颗树分别以树上每一个节点为根节点求hash值··将根节点的hash值储存起来排序然后两颗树一一比对··如果完全一样则两棵树就一样

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int N=55;
    int hash[N][N],n,que[N];
    int tot,fst[N],nxt[N*2],go[N*2],f[N];
    int prime[]={0,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,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317};
    inline void comb(int a,int b)
    {
      nxt[++tot]=fst[a],fst[a]=tot,go[tot]=b;
      nxt[++tot]=fst[b],fst[b]=tot,go[tot]=a;
    }
    inline void dfs(int u,int fa)
    {
      unsigned int st[N];int tot=0;  
      st[++tot]=1;
      for(int e=fst[u];e;e=nxt[e])
      {
        int v=go[e];if(v==fa)  continue;
        dfs(v,u);
        st[++tot]=f[v];
      }
      f[u]=0;sort(st+1,st+tot+1);
      for(int i=1;i<=tot;i++)  f[u]+=st[i]*prime[i];
    }
    int main()
    {
     // freopen("a.in","r",stdin);
      scanf("%d",&n);int a,b;
      for(int i=1;i<=n;i++)
      {
        scanf("%d",&a);
        memset(fst,0,sizeof(fst));tot=0;
        for(int j=1;j<=a;j++)  
        {
          scanf("%d",&b);
          if(b) comb(j,b);
        }
        for(int j=1;j<=a;j++)
        {
          dfs(j,0);hash[i][j]=f[j];
        }
        sort(hash[i]+1,hash[i]+a+1);
        for(int j=1;j<=i;j++)
        {
          bool flag=true;
          for(int k=1;k<=a;k++)
            if(hash[j][k]!=hash[i][k])  
            {  
              flag=false;break;
            }
          if(flag==true)  
          {       
            printf("%d
    ",j);
            break;
          }
        }
      }
      return 0;
    }
  • 相关阅读:
    eclipse internal web browser 不可用在linux下的解决
    Asp.Net MVC4入门指南(10):第三方控件Studio for ASP.NET Wijmo MVC4 工具应用
    生成树计数MatrixTree定理
    strcpy与strncpy
    [置顶] 游戏开发技术总结(经典之作)第七集 广阔天地游戏大地图的形成方法的地图移动
    Inside COM接口
    UTC时区表(.Net)
    java练习
    如果Imageview与Linearlayout有叠加且可选资源长度不同,如何布局?
    【Android测试】Android抓包解析全过程
  • 原文地址:https://www.cnblogs.com/AseanA/p/7633174.html
Copyright © 2011-2022 走看看