题意:
两棵树(10^5个节点) 问其中有多少对子树是同构的
思路:
树的同构一般使用hash来判断
hash函数为1、val=A 2、val = (val*P)^Soni%Q 其中Soni为第i个子树的hash值 3、val=val*B%Q
注意Son值应该排序 (本题因为左右子树是区分开的 因此不用排序)
代码:
#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<map> #include<set> #include<vector> #include<queue> #include<cstdlib> #include<ctime> #include<cmath> using namespace std; typedef unsigned long long ULL; #define N 100010 #define A 1333333331LL #define B 1333333333331LL #define P 133331LL #define Q 1333333333333331LL int T,n,m; int l[2][N],r[2][N]; ULL ans; map<ULL,ULL> cnt; ULL dfs(int u,int f){ ULL val=A; if(l[f][u]!=-1){ ULL tmp=dfs(l[f][u],f); val=((val*P)^tmp)%Q; }else{ ULL tmp=(A&B^P); val=((val*P)^tmp)%Q; } if(r[f][u]!=-1){ ULL tmp=dfs(r[f][u],f); val=((val*P)^tmp)%Q; }else{ ULL tmp=(A&B^P); val=((val*P)^tmp)%Q; } if(!f) cnt[val]++; else ans+=cnt[val]; return val; } int main(){ scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); cnt.clear(); ans=0; for(int i=1;i<=n;i++) scanf("%d%d",&l[0][i],&r[0][i]); for(int i=1;i<=m;i++) scanf("%d%d",&l[1][i],&r[1][i]); dfs(1,0); dfs(1,1); printf("%llu\n",ans); } return 0; }
原文地址:http://blog.csdn.net/houserabbit/article/details/43084491