题意
给两个二叉树,问两个二叉树有多少对点的子树相同
输入给出每个点的左右儿子,左右儿子在判断子树的时候是位置不同的
数据范围
解法
树hash模板,由于点数较多,所以需要比较强的hash(这次的树hash比上次的强非常多)
由于是二叉树,所以可以设置多个hash步长,一个给左儿子,一个给右儿子,然后还可以记录子树高度,计算左儿子hash的贡献时平方.总之怎么强怎么来.就可以通过了.(其实这个可以用多hash解决)
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
typedef unsigned long long ull;
const ull step1=233,step2=127;
inline int read(){
char c=getchar();int t=0,f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){t=(t<<3)+(t<<1)+(c^48);c=getchar();}
return t*f;
}
map<ull,long long> mp;
struct tree{
int n,ch[maxn][2],rt,ton[maxn],dep[maxn];
ull ha[maxn];
void dfs(int u){
if(ch[u][0]!=-1)dfs(ch[u][0]);
if(ch[u][1]!=-1)dfs(ch[u][1]);
if(ch[u][0]!=-1)dep[u]=dep[ch[u][0]]+1;
if(ch[u][1]!=-1)dep[u]=max(dep[u],dep[ch[u][1]])+1;
if(dep[u]==0)dep[u]=1;
ha[u]=dep[u];
if(ch[u][0]!=-1)ha[u]=ha[u]+step1*ha[ch[u][0]]*ha[ch[u][0]];
if(ch[u][1]!=-1)ha[u]=ha[u]+step2*ha[ch[u][1]];
}
void solve(){
for(int i=1;i<=n;i++)mp[ha[i]]++;
}
}t1,t2;
int main(){
t1.n=read(),t2.n=read();
for(int i=1;i<=t1.n;i++){
t1.ch[i][0]=read();t1.ch[i][1]=read();
if(t1.ch[i][0]!=-1)t1.ton[t1.ch[i][0]]=1;
if(t1.ch[i][1]!=-1)t1.ton[t1.ch[i][1]]=1;
}
for(int i=1;i<=t2.n;i++){
t2.ch[i][0]=read();t2.ch[i][1]=read();
if(t2.ch[i][0]!=-1)t2.ton[t2.ch[i][0]]=1;
if(t2.ch[i][1]!=-1)t2.ton[t2.ch[i][1]]=1;
}
for(int i=1;i<=t1.n;i++){
if(!t1.ton[i]){t1.rt=i;break;}
}
for(int i=1;i<=t2.n;i++){
if(!t2.ton[i]){t2.rt=i;break;}
}
t1.dfs(t1.rt);t2.dfs(t2.rt);
t1.solve();
long long ans=0;
for(int i=1;i<=t2.n;i++){
ans=ans+mp[t2.ha[i]];
}
printf("%lld\n",ans);
return 0;
}