jzoj 3957 鸡腿の花园

Description

【故事の背景】
 
鸡腿是CZYZ的著名DS,他为了树立高富帅的伟大形象决定暑假去张江大学学习(游玩)。张江大学自古以来就是充满了各种程序猿的地方,这里的花园自然也是十分奇葩,充满了符合程序猿口味的东西。鸡腿来到张江,自己也打理了一个小花园,小花园里种满了二叉树!
 
二叉树是什么呢,一棵树,除了根节点之外每个点都有父亲节点,同时每个节点只会有0个、1个或者2个孩子的树。
 
【问题の描述】
 
鸡腿在种树的过程中发现有两棵二叉树长的骨骼清奇,是树中极品。为了仔细研究这两颗树,鸡腿决定要研究一下这两棵树的共同点。鸡腿想让你帮他算一算,这两棵树上有多少相同的子树。
相同的子树指树A中的子树a和树B中的子树b完全相同,二叉树的相同定义为树上总节点个数相同,根节点孩子数相同,而且两棵子树分别相同。当然,孩子节点是有先后顺序的!

Data Constraint

对于20%的数据1 ≤ N,M ≤ 100;
对于40%的数据 1 ≤ N,M ≤ 5,000;
对于100%的数据 1 ≤ N,M ≤ 100,000。
 

Sol 

 Hash大法好。

 Hash函数随便写,怎么奇怪怎么来。

 

#include<bits/stdc++.h>
#define ull unsigned long long
using namespace std;
struct Hax{
    #define HaN 1234007
    int hea[HaN],net[HaN],fall[HaN],tot;
    ull key[HaN];
    int &get(ull _h){
        static int h;
        h=_h%HaN;
        for (int i=hea[h];i;i=net[i])
         if (key[i]==_h) return fall[i];
        key[++tot]=_h; net[tot]=hea[h]; hea[h]=tot;
        return fall[tot];
    }
    int Get(ull _h){
        static int h;
        h=_h%HaN;
        for (int i=hea[h];i;i=net[i])
         if (key[i]==_h) return fall[i];
        key[++tot]=_h; net[tot]=hea[h]; hea[h]=tot;
        return fall[tot];
    }
}f;
#define N 2000007
#define lx 23333
#define rx 998443
int siz[N],ch[N][2],n,m;
ull ha[N],ans;
void dfs(int x){
    if (ch[x][0]) dfs(ch[x][0]);
    if (ch[x][1]) dfs(ch[x][1]);
    siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    ha[x]=ha[ch[x][0]]*ha[ch[x][0]]*lx+ha[ch[x][1]]*rx+siz[x]^siz[ch[x][1]];
    f.get(ha[x])++;
}
void Dfs(int x){
    if (ch[x][0]) Dfs(ch[x][0]);
    if (ch[x][1]) Dfs(ch[x][1]);
    siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    ha[x]=ha[ch[x][0]]*ha[ch[x][0]]*lx+ha[ch[x][1]]*rx+siz[x]^siz[ch[x][1]];
    ans+=f.Get(ha[x]);
}
signed main () {
    freopen("1.in","r",stdin);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) {
     scanf("%d%d",ch[i],ch[i]+1); 
     if (ch[i][0]==-1) ch[i][0]=0;
     if (ch[i][1]==-1) ch[i][1]=0;
     }
    dfs(1);
    memset(ch,0,sizeof ch);
    memset(siz,0,sizeof siz);
    memset(ha,0,sizeof ha);
    for (int i=1;i<=m;i++) {
     scanf("%d%d",ch[i],ch[i]+1); 
     if (ch[i][0]==-1) ch[i][0]=0;
     if (ch[i][1]==-1) ch[i][1]=0;
     }
    Dfs(1);
    printf("%u\n",ans); 
    return 0;
}

 

posted @ 2018-07-16 16:07  泪寒之雪  阅读(292)  评论(0编辑  收藏  举报