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

    bzoj 4337 传送门

    这道题很显然是树的哈希裸题。

    有根树的哈希很简单,把子节点哈希值搞一搞(有各种搞法)就变成了本节点哈希值。

    再用map存一下就OK了。

    但是这道题是无根树,怎么选一个根开始深搜计算哈希值呢?

    可以使用树的重心。

    每棵树最多有两个重心,至少有一个重心。

    我们新建一个节点0。

    如果只有一个重心r1,就把0和r1连起来。

    如果有两个重心r1、r2,就把r1、r2之间的边断开,再分别从0向r1、r2连边。

    然后从0开始计算哈希值就好了。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<map>
      5 #define ull unsigned long long
      6 using namespace std;
      7  
      8 int m,n;
      9 int f[55];
     10 int hd[55],nx[105],to[105],cnt;
     11  
     12 map<ull,int>v;
     13  
     14 void add(int af,int at)
     15 {
     16     to[++cnt]=at;
     17     nx[cnt]=hd[af];
     18     hd[af]=cnt;
     19 }
     20  
     21 void build()//建树 
     22 {
     23     memset(hd,0,sizeof(hd));
     24     memset(nx,0,sizeof(nx));
     25     memset(to,0,sizeof(to));
     26     cnt=0;
     27     scanf("%d",&n);
     28     for(int i=1;i<=n;i++)
     29     {
     30         int q;
     31         scanf("%d",&q);
     32         if(q)add(q,i),add(i,q);
     33     }
     34 }
     35  
     36 int sz[55],mx[55];
     37 
     38 //深搜计算最大子树的重量 
     39 void dfs(int p,int fa)
     40 {
     41     sz[p]=1;
     42     for(int i=hd[p];i;i=nx[i])
     43     {
     44         if(to[i]==fa)continue;
     45         dfs(to[i],p);
     46         sz[p]+=sz[to[i]];
     47         mx[p]=max(mx[p],sz[to[i]]);
     48     }
     49     mx[p]=max(mx[p],n-sz[p]);
     50 }
     51  
     52 int r1,r2;
     53  
     54 void weigh()//找重心 
     55 {
     56     memset(sz,0,sizeof(sz));
     57     memset(mx,0,sizeof(mx));
     58     dfs(1,0);
     59     r1=1,r2=1;
     60     for(int i=1;i<=n;i++)
     61     {
     62         if(mx[i]<mx[r1])r1=i;
     63         if(mx[i]==mx[r1])r2=i;
     64     }
     65     add(0,r1),add(r1,0);
     66     //若有两个重心,把它们分别与新节点相连 
     67     if(mx[r1]==mx[r2]&&r1!=r2)add(0,r2),add(r2,0);
     68     //有一个重心 
     69     else r2=r1;
     70 }
     71 
     72 //深搜计算哈希值 
     73 ull cal(int p,int fa)
     74 {
     75     ull ret=1;
     76     ull st[55];
     77     int tp=0;
     78     for(int i=hd[p];i;i=nx[i])
     79     {
     80         if(to[i]==fa)continue;
     81         //两个重心之间的边不能走了 
     82         if(p==r1&&to[i]==r2)continue;
     83         if(p==r2&&to[i]==r1)continue;
     84         st[++tp]=cal(to[i],p);
     85     }
     86     for(int i=1;i<=tp;i++)ret+=st[i]*st[i];
     87     return ret;
     88 }
     89  
     90 int main()
     91 {
     92     scanf("%d",&m);
     93     for(int i=1;i<=m;i++)
     94     {
     95         build();
     96         weigh();
     97         ull h=cal(0,0);
     98         //map存一下 
     99         if(v.find(h)==v.end())v[h]=i;
    100         printf("%d
    ",v[h]);
    101     }
    102     return 0;
    103 }
    View Code

    把子节点的哈希值的平方加到一起作为本节点的哈希值,就能过。

    把子节点的哈希值分别乘上seed的不同次幂再加一起作为本节点的哈希值,就WA。

    不知道为什么......

  • 相关阅读:
    将博客搬至CSDN
    知道创建了SM30&nbsp;维护,怎么找…
    物料组件修改BAPI:BAPI_NETWORK_C…
    BAPI_NETWORK_COMP_REMOVE&nbsp;物料组…
    Python :Dive Into Python 中文版 读后感_第三章_内置数据结构
    Python :Dive Into Python 中文版 读后感_第三章_变量赋值
    Python :Dive Into Python 中文版 读后感_第四章__函数定义以及内置函数
    Python :Dive Into Python 中文版 读后感_第二章___需要注意的东西
    OutLook的网页版精美界面修改版
    .Net Framework2.0内部版本问题引起的错误!
  • 原文地址:https://www.cnblogs.com/cervusy/p/9984645.html
Copyright © 2011-2022 走看看