zoukankan      html  css  js  c++  java
  • BZOJ4337:[BJOI2015]树的同构(树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。

    Solution

    树hash,x的子树计算方法为$sum hash[i]*val[i]$,其中hash[i]表示的是x的儿子的第i大的哈希值,val[i]是随机的一组很大的数。

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<map>
     5 #include<algorithm>
     6 #define LL long long
     7 #define MOD (998244353)
     8 using namespace std;
     9 
    10 struct Edge{int to,next;}edge[201];
    11 LL T,n,x,ans,hash[101],val[101];
    12 int head[101],num_edge;
    13 map<LL,LL>Map;
    14 
    15 void add(int u,int v)
    16 {
    17     edge[++num_edge].to=v;
    18     edge[num_edge].next=head[u];
    19     head[u]=num_edge;
    20 }
    21 
    22 void Dfs(int x,int fa)
    23 {
    24     LL q[101],tot=0;
    25     hash[x]=0;
    26     for (int i=head[x]; i; i=edge[i].next)
    27         if (edge[i].to!=fa)
    28             Dfs(edge[i].to,x),q[++tot]=hash[edge[i].to];
    29     if (tot==0){hash[x]=1; return;}
    30     sort(q+1,q+tot+1);
    31     for (int i=1; i<=tot; ++i)
    32         hash[x]=(hash[x]+q[i]*val[i])%MOD;
    33 } 
    34 
    35 int main()
    36 {
    37     for (int i=1; i<=50; ++i)
    38         val[i]=rand()*233473ll+rand()*19260817ll+rand();
    39     scanf("%d",&T);
    40     for (int t=1; t<=T; ++t)
    41     {
    42         scanf("%d",&n);
    43         memset(head,0,sizeof(head)); num_edge=0;
    44         for (int i=1; i<=n; ++i)
    45         {
    46             scanf("%d",&x);
    47             if (!x) continue;
    48             add(x,i), add(i,x);
    49         }
    50         ans=233;
    51         for (int i=1; i<=n; ++i) 
    52         {
    53             Dfs(i,-1);
    54             if (!Map[hash[i]]) Map[hash[i]]=t;
    55             else Map[hash[i]]=min(Map[hash[i]],(LL)t);
    56             ans=min(ans,Map[hash[i]]);
    57         }
    58         printf("%lld
    ",ans);
    59     }
    60 }
  • 相关阅读:
    LA3971组装电脑
    LA3971组装电脑
    LA3905流星
    LA3905流星
    LA3902网络
    LA3902网络
    LA3708墓地雕塑
    洛谷 P2330 [SCOI2005]繁忙的都市(最小生成树)
    最小生成树 & 洛谷P3366【模板】最小生成树 & 洛谷P2820 局域网
    洛谷 P1372 又是毕业季I
  • 原文地址:https://www.cnblogs.com/refun/p/9552173.html
Copyright © 2011-2022 走看看