POJ 1240 Pre-Post-erous! && East Central North America 2002 (由前序后序遍历序列推出M叉树的种类)
题目链接:http://poj.org/problem?id=1240
本文链接:http://www.cnblogs.com/Ash-ly/p/5482520.html
题意:
通过一棵二叉树的中序和后序遍历序列,就可以得到这颗二叉树的前序遍历序列.类似的,也能通过前序和中序遍历序列来得到后序遍历序列.但是,通常来说,不能通过前序和后序遍历序列来确定一棵二叉树的中序遍历序列.如下面这四颗二叉树:
所有的这四颗二叉树都有着相同的前序(abc)和后序遍历(cba)序列.这个现象不仅仅在二叉树中存在,也同时在m叉树中存在.
给你m s1 s2,表示这是一颗m叉树,s1是其前序遍历序列,s2是其后序遍历序列.两个序列中只包含小写字母,且同一字母不会重复出现在同一个序列中.输入0代表输入结束,不做判断.对于每组输入,需要你输出一个数字,表示所给出的前序和后序遍历序列所表示的树一共有多少种可能.答案不会超出32位整形的数据范围.
思路:
首先对于m叉树的前序遍历序列,第一个字符一定表示这颗m叉树的根,在后序遍历序列中最后一个字符表示m叉树的根.前序遍历序列中的第二个字符x1,一定是m叉树根节点的第一棵子树的根节点,那么在后序遍历序列中,从开始部分到x1的部分一定是m叉树的第一颗子树的后序遍历序列,假设,这部分的个数为n1,那么在前序遍历序列中,从x1开始后的n1个字符一定是m叉树的第一颗子树的前序遍历序列.则在前序遍历序列中截掉这n1个字符以及代表根的字符后,在剩下的序列中,第一个字符x2一定是m叉树的第二棵子树的根节点.在后序遍历序列剩余的部分中,从头到x2的部分即是这第二颗子树的后序遍历序列,设节点个数为n2.那么在前序遍历序列中,从x2开始的n2个字符一定是这m叉树第二颗子树的前序遍历序列.以此类推,对于每棵树的前序和后序遍历序列,可以确定根节点的子节点是哪些,并且能够得到分别以这些子节点为根节点的子树的前序和后序遍历序列,如此的递归下去,可以知道这m叉树的层次结构和节点之间的父子关系以及兄弟节点之间的顺序关系.
节点之间的关系确定之后,需要确定一共有多少这样的m叉树.首先对于二叉树的情况,当一个根节点只有一个子节点时,这个儿子节点位于左二子或者右儿子的位置都会使得整个二叉树不同.那么类比到m叉树,如果m叉树某一个根节点只有n个子节点,那么这n个节点分别属于哪个树杈都会使得整个树的形状不一样.由于这n个节点的顺序是确定的,相当于把n个点顺序的放到m个位置,则有C(m , n)中放法.对于整棵树来说,树的种数等于每个节点的子节点位置的种数的乘积.
栗子:
13 abejkcfghid jkebfghicda
'a'是这13叉树的根节点,在前序遍历序列中'b'为这13叉树根节点'a'的第一颗子树的根,则在后序遍历序列中从'j'到'b'则为这第一棵子树的后序遍历序列,经计算共有四个节点,那么在前序遍历序列中,从'b'到'k'的这四个字符一定是第一颗子树的前序遍历序列.前序遍历序列中'k'后面的第一个字符'c',一定是这颗13叉树根节点'a'的第二颗子树的根,则在后序遍历序列中从'f'到'c'的五个字符一定是第二棵子树的后序遍历序列,那么在前序遍历序列中,从'c'往后再截取五个字符到'i',则说明这部分为第二棵子树的前序遍历序列.'i'之后的第一个字符'd'则为根节点'a'的第三棵子树的根节点,同样在后序遍历序列中'd'则为第三棵子树的后序遍历序列,在这里则说明第三棵子树只有一个根节点'd'.然后分别对第一颗子树和第二课子树前序以及后序遍历序列进行递归,从而得到子树根节点的子节点的个数以及顺序.由于根节点'a'有'b','c','d'这三个子节点,那么对于13叉树来说要把这三个节点顺序的放到13个位置则为C(13, 3).对于'a'的子节点'b'来说很明显仅有一个子节点'e',所以同样有C(13, 1)种放法,对于'e'节点则有两个子节点'j'和'k',那么种类为C(13, 2).对于'a'的第二个子节点'c'来说有4个子节点'f','g','h'及'i',那么总放法为C(13, 4),所以总的种数位C(13, 3) * C(13, 1) *C(13, 2) * C(13, 4) = 207352860.
代码:
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm> using namespace std;
typedef long long LL;
const int maxN = ;
char preord[maxN], enord[maxN];//前序遍历序列 以及 后续遍历序列 LL C(LL n, LL m){//计算组合数
if(m < n - m) m = n - m;
LL ans = ;
for(LL i = m + ; i <= n; i++) ans *= i;
for(LL i = ; i <= n - m; i++) ans /= i;
return ans;
} LL ans;
int n;
void possible(int preleft, int preright, int endleft, int endright){
int cnt = , root = preleft + ;//以preord[preleft]为根节点的第一个子节点preord[root]
while(root <= preright){
int i;
for(i = endleft; i <= endright; i++){//从剩余的后序遍历序列中确定以preord[root]为根节点的子节点个数
if(enord[i] == preord[root])break;
}
int size = i - endleft + ;//size即为preord[root]节点的根节点的个数
possible(root, root + size - , endleft, i);//preord[root~ (root + size - 1)] 为以preord[root]为根节点的子树的前序遍历序列, enord[endleft~i]则为其的后序遍历序列
cnt++; //子节点的个数加1
root += size;//root指向下一个子节点
endleft = i + ; //截掉后序遍历序列中endlft ~ i 的部分
}
ans *= C((LL)n, (LL)cnt);//累乘起来即是答案
} void solv(){
int len = strlen(preord);
possible(, len - , , len - );
printf("%lld\n", ans);
} int main(){
//freopen("input.txt", "r", stdin);
while(~scanf("%d", &n) && n){
memset(preord, , sizeof(preord));
memset(enord, , sizeof(enord));
scanf("%s%s", preord, enord);
ans = ;
solv();
}
return ;
}
POJ 1240 Pre-Post-erous! && East Central North America 2002 (由前序后序遍历序列推出M叉树的种类)的更多相关文章
- POJ 1240 Pre-Post-erous! && East Central North America 2002 (由前序后序遍历序列推出M叉树的种类)
题目链接 问题描述 : We are all familiar with pre-order, in-order and post-order traversals of binary trees. ...
- MPI Maelstrom(East Central North America 1996)(poj1502)
MPI Maelstrom 总时间限制: 1000ms 内存限制: 65536kB 描述 BIT has recently taken delivery of their new supercom ...
- poj 2732 Countdown(East Central North America 2005)
题意:建一个家庭树,找出有第d代子孙的名字,按照要求的第d代子孙的数从大到小输出三个人名,如果有一样大小子孙数的,就按字母序从小到大将同等大小的都输出,如果小于三个人的就全输出. 题目链接:http: ...
- Gym-101673 :East Central North America Regional Contest (ECNA 2017)(寒假自训第8场)
A .Abstract Art 题意:求多个多边形的面积并. 思路:模板题. #include<bits/stdc++.h> using namespace std; typedef lo ...
- 2017-2018 ACM-ICPC East Central North America Regional Contest (ECNA 2017) Solution
A:Abstract Art 题意:给出n个多边形,求n个多边形分别的面积和,以及面积并 思路:模板 #include <bits/stdc++.h> using namespace st ...
- East Central North America Region 2015
E 每过一秒,当前点会把它的值传递给所有相邻点,问t时刻该图的值 #include <iostream> #include <cstdio> #include <algo ...
- 2016-2017 ACM-ICPC East Central North America Regional Contest (ECNA 2016) F 区间dp
Problem F Removal GameBobby Roberts is totally bored in his algorithms class, so he’s developed a li ...
- 2014-2015 ACM-ICPC East Central North America Regional Contest (ECNA 2014) A、Continued Fractions 【模拟连分数】
任意门:http://codeforces.com/gym/100641/attachments Con + tin/(ued + Frac/tions) Time Limit: 3000/1000 ...
- East Central North America 2006 Hie with the Pie /// 状压dp oj22470
题目大意: 输入n,有n个地方(1~n)需要送pizza pizza点为0点 接下来n+1行每行n+1个值 表示 i 到 j 的路径长度 输出从0点到各点送pizza最后回到0点的最短路(点可重复走) ...
随机推荐
- Python数据分析(一)pandas数据切片
1.获取行或列数据 loc——通过行标签索引行数据 iloc——通过行号索引行数据 ix——通过行标签或者行号索引行数据(基于loc和iloc 的混合) 同理,索引列数据也是如此! import pa ...
- BZOJ4690 Never Wait for Weights(并查集)
带权并查集按秩合并即可维护. #include<iostream> #include<cstdio> #include<cmath> #include<cst ...
- 【AtCoder】ARC 081 E - Don't Be a Subsequence
[题意]给定长度为n(<=2*10^5)的字符串,求最短的字典序最小的非子序列字符串. http://arc081.contest.atcoder.jp/tasks/arc081_c [算法]字 ...
- 【ZJ选讲·画山】
给出一张纸(N × M),你要在上面画山,但不能画出界(N,M<=100) Like this: 起点为(0,0),终点为(N,0) 给出w种线段画法(x,y),表示用了这种画法后,笔迹末 ...
- 【模拟赛·polyline】
Input file: polyline.in Output file: polyline.out Time limit: 1s Memory limit: 128M 有若⼲个类似于下⾯的函数: 定义 ...
- loj2540 「PKUWC 2018」随机算法
pkusc 快到了--做点题涨涨 rp. 记 \(f(S,i)\) 表示 \(S\) 这个集合是决计不能选的(要么属于独立集,要么和独立集相连),或称已经考虑了的,\(i\) 表示此集合对应的最大独立 ...
- bzoj2002: [Hnoi2010]Bounce 弹飞绵羊 分块
这个题体现了分块不只是最大值最小值众数次数,而是一种清真的思想. 我们把整个序列分块,在每个块里处理每个位置跳出这个块的次数和跳出的位置,那么每次修改n0.5,每次查询也是,那么O(m* n0.5)的 ...
- JQuery用鼠标选文字来发新浪微博
最近注意到新浪博客有个小功能,就是当鼠标选中一段文字时会浮现一个小图片,点击这个图片可以把选中内容发送到新浪微博,一时兴起昨晚就写了一个Demo玩了一下,代码超简单,没优化,有兴趣的朋友可以自己改进. ...
- 整理一些JavaScript时间处理扩展函数
在JavaScript中,时间处理是经常需要用到的.最近想要慢慢建立自己的代码库,整理了几个之前用到的js处理时间的函数,发出来跟大家分享一下,以后的使用中会不断增加和修改代码库. 把字符串转换为日期 ...
- 2015年网易校招Java开发工程师(技术架构)在线笔试题
1. 程序和进程的本质区别是? A.在外存和内存存储 B.非顺序和顺序执行机器指令 C.独占使用和分时使用计算机资源 D.静态和动态特征 参考答案分析: 进程与应用程序的区别: 进程(Process ...