ZOJ 3602 树的同构
题意:
给出 n m 代表第一棵树有 n 个节点 第二棵树有 m 个节点
然后接下来 n+m 行给出 a b 表示第 i 个节点的左孩子是 a 右孩子是 b
问这两棵树中有多少棵子树是相同的..
eg:
Sample Input 2 2 2 -1 2 -1 -1 2 -1 -1 -1 5 5 2 3 4 5 -1 -1 -1 -1 -1 -1 2 3 4 5 -1 -1 -1 -1 -1 -1 Sample Output 1 11 Hint The two trees in the first sample look like this.
思路:
根据输入的信息建树..
用 deg 数组记录这棵树的第 i 个节点有多少棵子树..
用 hash[ t ][ i ] 表示第 t 棵树中第 i 个节点的 hash 值是多少..
用 sum[ t ][ i ] 表示第 t 棵树种 hash 值是 i 的子树有多少棵..
先处理第一棵树..
从叶子节点开始处理.. 把是叶子节点的都加入队列..
然后根据 map<pair<L, R>, p>.. 把这棵树的每个节点都映射成唯一表示的值..
第一次接触 hash.. 感觉hash就是根据一定方法找到一个 key 值唯一标识对应给出的信息..然后通过 key 值找给出的数据..
这里 hash 值的处理方法是定义一个结构体 pair<int, int> 表示该节点的左右孩子
然后用 map<pair<L, R>, p> 映射来唯一表示这个节点 p..对叶子节点统一 映射为 pair<-1, -1>
根据左右孩子的特征值再唯一确定节点 p 的 hash 值 mp[p] = mp.size()+1..
对应sum[ t ][p节点对应hash值] ++ 来表示有过这个状态的子树..
处理第二棵树的时候..
用同样的方法求出特征值以及对应的hash值..
然后看在第一棵树中有没有这种状态的树..
用 ans += sum[ t ][ mp[p] ];求出要求的解..
其中每处理完一个节点..就让它的根节点的对应deg[ ]--;当deg[父节点]退化为叶子节点..就加入队列..
Tips:
※ deg[ 0 ] 是头头节点..为了防止被加入队列..一开始应该初始化为 3
※ 因为 n 和 m 很大..所以答案的范围应该定义为 长整型
Code:
1 #include <stdio.h> 2 #include <cstring> 3 #include <algorithm> 4 #include <map> 5 #include <queue> 6 using namespace std; 7 #define clr(x) memset(x, 0, sizeof(x)) 8 const int maxn = 100010; 9 10 struct Node 11 { 12 int ff; 13 int ls; 14 int rs; 15 }node[2][maxn]; 16 17 int sum[2][maxn], hash[2][maxn], deg[maxn], n[2]; 18 map<pair<int, int>, int> mp; 19 long long ans;///!!! 20 21 void bfs(int t) 22 { 23 queue<int> Q; 24 int tmp, L, R; 25 int i, j, k; 26 deg[0] = 3; 27 28 for(i = 1; i <= n[t]; ++i) 29 { 30 deg[i] = (node[t][i].ls != -1) + (node[t][i].rs != -1); 31 if(deg[i] == 0) 32 { 33 Q.push(i); 34 hash[t][i] = 0; 35 } 36 } 37 38 while(!Q.empty()) 39 { 40 tmp = Q.front(); 41 Q.pop(); 42 43 L = -1; 44 if(node[t][tmp].ls != -1) 45 L = hash[t][node[t][tmp].ls]; 46 R = -1; 47 if(node[t][tmp].rs != -1) 48 R = hash[t][node[t][tmp].rs]; 49 50 pair<int, int> p = make_pair(L, R); 51 if(mp[p] == 0) mp[p] = mp.size()+1; 52 sum[t][mp[p]]++; 53 hash[t][tmp] = mp[p]; 54 55 if(t == 1) ans += sum[0][mp[p]]; 56 57 deg[node[t][tmp].ff]--; 58 if(deg[node[t][tmp].ff] == 0) { 59 Q.push(node[t][tmp].ff); 60 } 61 } 62 } 63 64 65 int main() 66 { 67 int i, j, k; 68 int T, nn, mm; 69 while(scanf("%d", &T) != EOF) 70 while(T--) 71 { 72 73 mp.clear(); 74 ans = 0; 75 node[0][1].ff = node[1][1].ff = 0; 76 memset(sum, 0, sizeof(sum)); 77 78 scanf("%d %d", &nn, &mm); 79 n[0] = nn, n[1] = mm; 80 for(i = 0; i < 2; ++i) 81 for(j = 1; j <= n[i]; ++j) 82 { 83 scanf("%d %d", &node[i][j].ls, &node[i][j].rs); 84 if(node[i][j].ls != -1) node[i][node[i][j].ls].ff = j; 85 if(node[i][j].rs != -1) node[i][node[i][j].rs].ff = j; 86 } 87 88 bfs(0), bfs(1); 89 90 printf("%lld\n", ans); 91 } 92 return 0; 93 }