链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4705
题意:给出两棵二叉树A和B,问分别处于A中的子树a和处于B中的子树b结构相同的有多少对。
思路:哈希的想法,不同的数字对应的是不同的结构,比如1代表着单独的叶子结点,2代表着有左子树是叶子结点而没有右子树的子树...每出现一种新的子树情形就记录下来,记录的方式是用dfs回溯过程中判断左子树和右子树组成的子树是否出现过(用pair记录子树的情况,也就是左右子树,两个map,第一个map表示子树的pair与它的标号的映射,第二个map表示每种标号出现的次数)。
代码:
#include <algorithm> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <ctype.h> #include <iostream> #include <map> #include <queue> #include <set> #include <stack> #include <string> #include <vector> #define eps 1e-8 #define INF 0x7fffffff #define maxn 100005 #define PI acos(-1.0) #define seed 31//131,1313 typedef long long LL; typedef unsigned long long ULL; using namespace std; int top=0; map < pair < int , int > , int > M; map < int , LL > N ; int tree_a[maxn][2],tree_b[maxn][2],a[maxn],b[maxn]; LL ans; void dfs_a(int u) { pair < int , int > p; int left,right; left=tree_a[u][0],right=tree_a[u][1]; if(left!=-1) dfs_a(left); if(right!=-1) dfs_a(right); if(left==-1) p.first=-1; else p.first=a[left]; if(right==-1) p.second=-1; else p.second=a[right]; if(M.find(p)==M.end()) { M[p]=top; a[u]=top; N[top]=1; top+=3; } else { a[u]=M[p]; N[M[p]]++; } } void dfs_b(int u) { pair <int ,int > p ; int left=tree_b[u][0],right=tree_b[u][1]; if(left!=-1) dfs_b(left); if(right!=-1) dfs_b(right); if(left==-1) p.first=-1; else p.first=b[left]; if(right==-1) p.second=-1; else p.second=b[right]; if(M.find(p)!=M.end()) { ans+=N[M[p]]; b[u]=M[p]; } } void init() { top=0; ans=0; N.clear(); M.clear(); for(int i=0;i<=100000;i++) a[i]=-2,b[i]=-2; } int main() { int T,n,m; scanf("%d",&T); while(T--) { init(); scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) scanf("%d%d",&tree_a[i][0],&tree_a[i][1]); for(int i=1; i<=m; i++) scanf("%d%d",&tree_b[i][0],&tree_b[i][1]); dfs_a(1); dfs_b(1); printf("%lld\n",ans); } return 0; }
ZOJ 3602 Count the Trees 树的同构 (哈希)
原文地址:http://blog.csdn.net/ooooooooe/article/details/39082409