ZOJ 3602 树的同构

题意:

给出 n m 代表第一棵树有 n 个节点 第二棵树有 m 个节点

然后接下来 n+m 行给出 a b 表示第 i 个节点的左孩子是 a 右孩子是 b

问这两棵树中有多少棵子树是相同的..

eg:

View Code
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:

View 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 }

 

 

 

posted @ 2012-09-11 17:16  Griselda.  阅读(1070)  评论(0编辑  收藏  举报