UVa 10410 树重建
Tree Reconstruction
Problem Description
You have just finished a compiler design homework question where you had to find the parse tree of an expression. Unfortunately you left your assignment in the library, but luckily your friend picked it up for you. Instead of e-mailing you the parse tree so that you can rewrite the solution, your friend decides to play a practical joke and sends you just the DFS and BFS trace. Rather than try to redo the entire question you decide to reconstruct the tree.
思路分析
首先这不是一道普通的根据BFS和DFS建树,因此我们需要分析这种树的遍历的性质。普通性质无需多说,这里只说必要的。
对于BFS:
同层的节点BFS编号顺序在DFS中也是按顺序出现的。根据这个我们可以一次遍历算出节点 的深度。
对于DFS:
一个节点的子孙肯定在他后面,在他同层相邻节点的前面。
对于一个节点的子孙,如果他们有的深度恰好等于这个节点的深度+1,那么这些子孙肯定是这个节点的儿子。
有了这些性质我们就可以递归建树了。
代码展现
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
//#pragma GCC optimize(2)
using namespace std;
#define ll long long
const int maxn=1010;
const int INF=0x7fffffff;
inline void read(int&x){
int data=0,w=1;
char ch=getchar();
while(ch!='-'&&!isdigit(ch))
ch=getchar();
if(ch=='-')
w=-1,ch=getchar();
while(isdigit(ch))
data=10*data+ch-'0',ch=getchar();
x=data*w;
}
void write(int x){
if(x<0)
putchar('-'),x=-x;
if(x>9)
write(x/10);
putchar('0'+x%10);
}
struct vertex{
int depth;
int bfsrank;
int dfsrank;
list<int> edge;
void clear(){
depth=bfsrank=dfsrank=0;
edge.clear();
}
void addedge(int v){
edge.push_back(v);
}
}v[maxn];
int bfsans[maxn],dfsans[maxn];
#define root bfsans[1]
void build(int o,int l,int r){
// clog<<"in o:"<<o<<" l:"<<l<<" r:"<<r<<endl;
for(int i=l;i<=r;++i)
if(v[dfsans[i]].depth==v[o].depth+1)
v[o].addedge(dfsans[i]);
if(v[o].edge.size()){
list<int>::iterator i=v[o].edge.begin(),ed=v[o].edge.end();
--ed;
while(i!=ed){
build(*(i++),v[*(--i)].dfsrank+1,v[*(++i)].dfsrank-1);
}
build(*ed,v[(*ed)].dfsrank+1,r);
}
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int n,whodep;
while(cin>>n){
for(int i=1;i<=n;++i)
v[i].clear();
for(int i=1;i<=n;++i){
read(bfsans[i]);
v[bfsans[i]].bfsrank=i;
}
for(int i=1;i<=n;++i){
read(dfsans[i]);
v[dfsans[i]].dfsrank=i;
}
/* clog<<"dfsrank:"<<endl;
for(int i=1;i<=n;i++)
clog<<i<<": "<<v[i].dfsrank<<endl;*/
v[root].depth=0;
whodep=1;
for(int i=2;i<=n;++i){
if(v[bfsans[i]].dfsrank<v[bfsans[i-1]].dfsrank)
++whodep;
v[bfsans[i]].depth=whodep;
}
/* clog<<"depths: "<<endl;
for(int i=1;i<=n;++i)
clog<<i<<": "<<v[i].depth<<endl;*/
build(root,2,n);
for(int i=1;i<=n;++i){
write(i);putchar(':');putchar(' ');
if(v[i].edge.size()){
list<int>::iterator j=v[i].edge.begin();
while(j!=v[i].edge.end()){
write(*j);putchar(' ');
++j;
}
}
putchar('\n');
}
}
// fclose(stdin);
// fclose(stdout);
return 0;
}
认真看了的同学应该会注意到67行我的奇怪写法。为何不写成build(\*i,v[\*i].dfsrank+1,v[\*(++i)].dfsrank-1);呢?
这背后就是我写这篇博客的主要原因。上述代码是错的。
万恶之源是函数参数压栈顺序(CALLBACK),他是从右到左压栈的。这样的话上述代码问题就很严重了。我之前就是那样写的,想不到这种注意事项让我碰上了。卡了我半中午啊o(╥﹏╥)o。谁让 std::list::iterator 不支持+1操作呢?
教训惨重......
UVa 10410 树重建的更多相关文章
- UVa 10410树重建
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- UVA 536 TreeRocvery 树重建 (递归)
根据先序历遍和中序历遍输出后序历遍,并不需要真的建树,直接递归解决 #include<cstdio> #include<cstring> ; char preOrder[N]; ...
- UVA - 10410 Tree Reconstruction (根据dfs序和bfs序恢复一颗树)
题意: 分析: 这题一开始完全没有思路, 一直没有找出规律. 参考了http://www.cnblogs.com/Wade-/p/6358859.html 和 http://www.cnblogs.c ...
- 剑指offer 4.树 重建二叉树
题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ...
- UVa 112 树求和
题意:给定一个数字,以及一个描写叙述树的字符序列,问存不存在一条从根到某叶子结点的路径使得其和等于那个数. 难点在于怎样处理字符序列.由于字符间可能有空格.换行等. 思路:本来想着用scanf的(后发 ...
- uva 12086 树状数组
树状数组 #include <cstdio> #include <cstdlib> #include <cmath> #include <map> #i ...
- UVa 1220 (树的最大独立集) Party at Hali-Bula
题意: 有一棵树,选出尽可能多的节点是的两两节点不相邻,即每个节点和他的子节点只能选一个.求符合方案的最大节点数,并最优方案判断是否唯一. 分析: d(u, 0)表示以u为根的子树中,不选u节点能得到 ...
- UVA 10410 Tree Reconstruction
题意: 给定一个树的BFS和DFS,求这棵树. 分析: 拿dfs的序列,分成若干段,每一段相当一个子树,这样就可以利用bfs的序列去将dfs的序列分段,然后利用一个队列去存放每一段,不断求出子树即可. ...
- Uva 122 树的层次遍历 Trees on the level lrj白书 p149
是否可以把树上结点的编号,然后把二叉树存储在数组中呢?很遗憾如果结点在一条链上,那将是2^256个结点 所以需要采用动态结构 首先要读取结点,建立二叉树addnode()+read_input()承担 ...
随机推荐
- 如何配置Smarty模板
<?php //首先包含Smarty类文件 include_once('Smarty/Smarty.class.php'); //实例化Smarty类文件 $smarty=new Smarty( ...
- UVA-1252 Twenty Questions (状压DP)
题目大意:有n件物品,每件物品有m个特征,可以对特征进行询问,询问的结果是得知某个物体是否含有该特征,要把所有的物品区分出来(n个物品的特征都互不相同)最小需要多少次询问? 题目分析:定义dp(s,a ...
- 常用OS获取信息命令
一.linux#CPU信息(总核心数和型号) cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c #物理CPU数及每颗物理CPU中核心数(可能有 ...
- 学习浏览器缓存(http缓存)
Q: 浏览器缓存是个什么东东,为什么要学习浏览器缓存涅? A: 浏览器缓存其实就是浏览器保存通过HTTP获取的所有资源,是浏览器将网络资源存储在本地的一种行为.浏览器缓存可以减少冗余数据的传输,减小服 ...
- CentOS下tar解压 gz解压 bz2等各种解压文件使用方法
.tar 解包:tar xvf FileName.tar 打包:tar cvf FileName.tar DirName (注:tar是打包,不是压缩!) ——————————————— . ...
- Maven 入门篇 ( 上 )
写这个 maven 的入门篇是因为之前在一个开发者会的动手实验中发现挺多人对于 maven 不是那么了解,所以就有了这个想法.这个入门篇分上下两篇.本文着重动手,用 maven 来构建运行 hello ...
- 福大软工 · BETA 版冲刺前准备
拖鞋旅游队BETA 版冲刺前准备 前言 队名:拖鞋旅游队 组长博客:https://www.cnblogs.com/Sulumer/p/10083834.html 本次作业:https://edu.c ...
- Java内存不足之PermGen space错误探究
一.Java 程序的运行机制与普通程序,如C或C++ 程序的运行机制有很大的区别. 普通程序运行之前必须首先编译成可执行的二进制码或机器码.机器码是与底层的硬件结构相关的,即使书写源代码的时候没有利用 ...
- 【记录】恢复win7与ARM开发板TQ2440的串口连接
1.给板子上电. 2.接好物理上的串口连接,板子那端就是普通的RS232串口,电脑这端是USB转串口的线的USB这头,连到电脑上,然后在Win7系统下,先去看看,当前连接的USB虚拟出来的串口是哪个口 ...
- ABP .Net Core 调用异步方法抛异常A second operation started on this context before a previous asynchronous operation completed
1. 问题描述 最近使用ABP .Net Core框架做一个微信开发,同时采用了一个微信开发框架集成到ABP,在微信用户关注的推送事件里调用了一个async 方法,由于没有返回值,也没做任何处理,本 ...