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