POJ1635:Subway tree systems

——初始时站在树的根节点,若朝着远离根的方向走,记录“0”,接近根的方向走记录“1”。并且树的每一条边只能来回走一次(即向下和返回)。一个合法的01序列可以描述出一棵树的形态。现在给出两个合法的01序列,判断两棵树是否同构。

——树的同构

——url:http://poj.org/problem?id=1635

————————————————————————————————————————————————————

【转载】

由于根节点确定,若两棵树同构,无非就是把子树的位置交换了一下。很自然的想法就是:将树的子树按照某种规则进行排序,若排序之后两个字符串相等,则同构;否则不同构。

现在来分析一下01序列,可以看出,当一个串的“0”和“1”个数相等时,恰好就是一棵子树。例如:

0010011101001011

可以划分为一下三棵子树

00100111,01,001011

而对于每部分划分来说,去掉第一个0和末尾的1,得到的就遍历是这棵子树的01序列(空串表示子树为空)。这样便出现了递归结构

将这棵树最小表示的算法描述如下:

0、若01序列为空,返回。

1、划分出该01序列的每一棵子树。

2、对于每棵子树,去掉第一个0和末尾1之后,递归进行最小表示。

3、得到每棵子树的最小表示后,将子树的01串按照strcmp排序。

View Code
 1 #include<stdio.h>
2 #include<algorithm>
3 #include<string.h>
4 #include<vector>
5 #include<string>
6 using namespace std;
7 #define LEN 3010
8 char tem[LEN], str1[LEN], str2[LEN];
9 int cas;
10 void solve(char s[], int l, int r)
11 {
12 int i, j, k, count = 0;
13 vector<string> h;
14 if (l > r)
15 return;
16 j = l;
17 for (i = l; i <= r; i++)
18 {
19 if (s[i] == '0')
20 count++;
21 else
22 count--;
23 if (count == 0)
24 {
25 solve(s, j + 1, i - 1);
26 for (k = j; k <= i; k++)
27 tem[k - j] = s[k];
28 tem[i - j + 1] = '\0';
29 h.push_back(tem);
30 j = i + 1;
31 }
32 }
33 sort(h.begin(), h.end());
34 k = l;
35 for (i = 0; i < h.size(); i++)
36 for (j = 0; j < h[i].size(); j++)
37 s[k++] = h[i][j];
38 h.clear();
39 }
40 int main()
41 {
42 scanf("%d", &cas);
43 getchar();
44 while (cas--)
45 {
46 gets(str1);
47 gets(str2);
48 solve(str1, 0, strlen(str1) - 1);
49 solve(str2, 0, strlen(str2) - 1);
50 if (strcmp(str1, str2) == 0)
51 printf("same\n");
52 else
53 printf("different\n");
54 }
55 return 0;
56 }

  


posted on 2011-09-15 21:54  风也轻云也淡  阅读(197)  评论(0编辑  收藏  举报