zoukankan      html  css  js  c++  java
  • 【树hs】[BJOI2015]树的同构

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

    这道题是树hs裸题,树hs的思路就是,先把每个节点的点权赋为1,然后父节点累加子节点平方和自己的值向上返回,

    就是一个递归的过程,然后自然溢出

    但是每个树的根节点可能会不同,所以我们要有对于每个树选根的唯一标准

    对,就是树重心,一个树可能有多个重心,那么我们只需要一个超级原点就ok 了

    最后比较超级原点的hs值,就能知道是否同构

    有一点玄学的地方,就是用seed的方式过不了,也不知道是为什么

     1 #include<bits/stdc++.h>
     2 #define N 100
     3 #define clear(a,val) memset(a,val,sizeof(a))
     4 using namespace std;
     5 typedef unsigned long long ult;
     6 int n,m,f,cnt=1,pp;
     7 int head[N],nxt[N*2],to[N*2],size[N],ans[N];
     8 ult vv[N],val[N];
     9 inline void add(int u,int v)
    10     {nxt[cnt]=head[u],to[cnt]=v,head[u]=cnt++;}
    11 inline void cl(){
    12     clear(size,0),clear(ans,0),clear(head,-1),cnt=1,pp=0;
    13 }
    14 int dfs(int now,int fa)
    15 {
    16     size[now]=1;int ma=-1;
    17     for(int i=head[now];i!=-1;i=nxt[i])
    18     {
    19         int t=to[i];
    20         if(t==fa)continue;
    21         size[now]+=dfs(t,now);
    22         ma=max(ma,size[t]);
    23     }
    24     ma=max(ma,n-size[now]);
    25     if(ma<=(n>>1))ans[++pp]=now;
    26     return size[now];
    27 }
    28 inline void weigh()
    29 {
    30     dfs(1,-1);
    31     for(int i=1;i<=pp;i++)
    32         add(n+1,ans[i]);
    33 }
    34 ult cal(int now,int fa)
    35 {
    36     vv[now]=1;
    37     for(int i=head[now];i!=-1;i=nxt[i])
    38     {
    39         int t=to[i];
    40         if(t==fa)continue;
    41         vv[now]+=cal(t,now);
    42     }
    43     return vv[now]*vv[now];
    44 }
    45 inline void init_build_weigh_solve()
    46 {
    47     clear(head,-1);
    48     scanf("%d",&m);
    49     for(int i=1;i<=m;i++)
    50     {
    51         cl();
    52         scanf("%d",&n);
    53         for(int j=1;j<=n;j++)
    54         {
    55             scanf("%d",&f);
    56             if(f==0)continue;
    57             else add(f,j),add(j,f);
    58         }
    59         weigh();
    60         val[i]=cal(n+1,-1);
    61     }
    62     for(int i=1;i<=m;i++)
    63     {
    64         for(int j=1;j<=i;j++)
    65         {
    66             if(val[i]==val[j])
    67             {
    68                 printf("%d
    ",j);
    69                 break;
    70             }
    71         }
    72     }
    73 }
    74 int main()
    75 {
    76     init_build_weigh_solve();
    77     return 0;
    78 }
  • 相关阅读:
    05_python_字典
    04_python_列表
    03_python_基本数据类型
    02_python_while循环/格式化输出/逻辑运算
    01_python_初始python
    vue中v-model的数据双向绑定(重要)
    vue中轮播图的实现
    侦听器watch 监听单个属性
    vue computed监听多个属性
    vue中ajax应用
  • 原文地址:https://www.cnblogs.com/Qin-Wei-Kai/p/10204381.html
Copyright © 2011-2022 走看看