Problem UVA10410-Tree Reconstruction

Accept:708  Submit:4330

Time Limit: 3000 mSec

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.

 Input

The input file contains several test cases as described below.

The first line of a input is the number n (1 <= n <= 1000) of nodes in the tree. The nodes in the tree are numbered 1, 2, ..., n. The remaining numbers are the BFS traversal followed by the DFS traversal. Note that when a parent was expanded the children were traversed in ascending order.

 Output

The output for each case should consist of n lines, one for each node. Each line should start with the node number followed by a colon followed by a list of children in ascending order. If there is more than one solution, any correct answer is acceptable.

 Sample Input

8
4 3 5 1 2 8 7 6
4 3 1 7 2 6 5 8
 
 

 Sample Ouput

1: 7
2: 6
3: 1 2
4: 3 5
5: 8
6:
7:
8:

题解:一道好题!我自己模拟的时候思路很凌乱,始终找不到一个可以实现的算法,翻看了很多题解,发现有很多题解和代码都是错的,写的比较好的博客链接如下:

http://www.cnblogs.com/jerryRey/p/4622927.html

我们先来列举两条性质:

1.在BFS序中,与点a相邻的下一个点可能有三种身份:(1)节点a的孩子 (2)节点a的第一后兄弟 (3)节点a的兄弟的孩子

2.在DFS序中,与点a相邻的下一个点可能有三种身份:(1)节点a的孩子(2)节点a的第一后兄弟(3)啥也不是(意思是说直接回到父辈及以上了)

用这两条性质我们来推出一个重要结论,设节点u,v,他们的BFS序分别设为bfs(u),bfs(v).

设这两个点在DFS序中是相邻的并且v是u的下一个节点。

结论:如果bfs(v) = bfs(u)+1 并且v>u那么,v必定可以视为u的第一后兄弟。

关键字是视为。这是相当于u,v在两个序列里都相邻,对比上文所说的三种身份,三种身份只剩两种了。如果v是u的孩子,由于二者在BFS序中相邻,因此和u在同一层的节点都遍历到了,如果u的同一层还有别的节点,那么v一定是u前面的兄弟的孩子,而此时v时u的孩子,因此,u所在的那一层只有u一个,我们把v及其子树提上来,让v变成u的后兄弟,显然不改变BFS序和DFS序,因此就证明了刚才的结论。

有了这个结论就好办多了,如果bfs(v) > bfs(u)+1那么它不可能是u的后兄弟,只能是u的孩子,证明很简单,对比三种身份,v不能是节点u的第一后兄弟,因为他们的BFS序不相邻,v不可能啥也不是,因为v的BFS序在u后面,如果v回到u的父辈及以上了,它必定出现早于u。如果bfs(v) < bfs(u)那就只能是啥也不是的情况了,这个时候怎么办,在DFS序中v回到了u的父辈及以上。那就代表着u及其子树被处理完了,忽略u就好,具体实现时弹栈就好。这里并没有把所有情况都涵盖,但是简单思考就知道那些情况对于一棵合法的树来说是不可能的。

还要注意一个细节就是栈顶元素时root时,直接加孩子,入栈。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <stack>
using namespace std; const int maxn = +;
int bfs_order[maxn];
vector<int> child[maxn]; int main()
{
//freopen("input.txt","r",stdin);
int n;
while(~scanf("%d",&n)){
int x;
for(int i = ;i <= n;i++){
child[i].clear();
scanf("%d",&x);
bfs_order[x] = i;
}
stack<int> sta;
int root;
scanf("%d",&root);
sta.push(root);
for(int i = ;i < n;i++){
scanf("%d",&x);
while(true){
int temp = sta.top();
if((bfs_order[x]>bfs_order[temp]+) || (bfs_order[x]==bfs_order[temp]+ && temp>x) || (temp==root)){
child[temp].push_back(x);
sta.push(x);
break;
}
else sta.pop();
}
}
for(int i = ; i <= n; i++) {
printf("%d:",i);
for(int j = ;j < child[i].size();j++){
printf(" %d",child[i][j]);
}
printf("\n");
}
}
return ;
}

UVA10410-Tree Reconstruction(BFS序和DFS序的性质)的更多相关文章

  1. 括号序和dfs序

    记得清北讲过括号序和dfs序,忘记了 dfs序 dfs序就是dfs的顺序,这个好记 就是在dfs遍历树的时候,将每个结点开始时记录一次,结束时记录一次 而且一个子树可以表示为连续的一段, 只有子树操作 ...

  2. 【SPOJ】10628. Count on a tree(lca+主席树+dfs序)

    http://www.spoj.com/problems/COT/ (速度很快,排到了rank6) 这题让我明白了人生T_T 我知道我为什么那么sb了. 调试一早上都在想人生. 唉. 太弱. 太弱. ...

  3. Codeforces Round #200 (Div. 1) D Water Tree 树链剖分 or dfs序

    Water Tree 给出一棵树,有三种操作: 1 x:把以x为子树的节点全部置为1 2 x:把x以及他的所有祖先全部置为0 3 x:询问节点x的值 分析: 昨晚看完题,马上想到直接树链剖分,在记录时 ...

  4. HDU5293(SummerTrainingDay13-B Tree DP + 树状数组 + dfs序)

    Tree chain problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Other ...

  5. HDU 6191 Query on A Tree(可持久化Trie+DFS序)

    Query on A Tree Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Othe ...

  6. CodeForces 375D Tree and Queries 莫队||DFS序

    Tree and Queries 题意:有一颗以1号节点为根的树,每一个节点有一个自己的颜色,求出节点v的子数上颜色出现次数>=k的颜色种类. 题解:使用莫队处理这个问题,将树转变成DFS序区间 ...

  7. S - Query on a tree HDU - 3804 线段树+dfs序

    S - Query on a tree HDU - 3804   离散化+权值线段树 题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度. 这个题目和之前写的那个给你一棵 ...

  8. HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...

  9. codeforces 375D . Tree and Queries 启发式合并 || dfs序+莫队

    题目链接 一个n个节点的树, 每一个节点有一个颜色, 1是根节点. m个询问, 每个询问给出u, k. 输出u的子树中出现次数大于等于k的颜色的数量. 启发式合并, 先将输入读进来, 然后dfs完一个 ...

随机推荐

  1. Netty实战十一之预置的ChannelHandler和编解码器

    Netty为许多通用协议提供了编解码器和处理器,几乎可以开箱即用,这减少了你在那些相当繁琐的事务上本来会花费的时间与精力.我们将探讨这些工具以及它们所带来的好处,其中包括Netty对于SSL/TLS和 ...

  2. JavaScript 延迟加载

    默认情况下,浏览器是同步加载 JavaScript 脚本,即渲染引擎遇到<script>标签就会停下来,等到执行完脚本,再继续向下渲染.如果是外部脚本,还必须加入脚本下载的时间. 如果脚本 ...

  3. Java自动内存管理机制学习(一):Java内存区域与内存溢出异常

    备注:本文引用自<深入理解Java虚拟机第二版> 2.1 运行时数据区域 Java虚拟机在执行Java程序的过程中把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创 ...

  4. WORLD 快速线

    1,3个“-”     一条直线 2,3个“=”    一条双直线 3,3个“*”     一条虚线 4,3个“~”     一条波浪线 5, 3个“#”    一条隔行线

  5. es6 语法 (类与对象)

    { // 基本定义和生成实例 class Parent{ constructor(name='mukewang'){ this.name=name; } } let v_parent1=new Par ...

  6. JavaScript易错知识点整理[转]

    前言 本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一 ...

  7. 2018-05-09 5分钟入门CTS-尝鲜中文版TypeScript

    知乎原链 本文为中文代码示例之5分钟入门TypeScript的CTS版本. CTS作者是@htwx(github). 它实现了关键词和标准库的所有命名汉化. 本文并未使用附带的vscode相关插件(包 ...

  8. CSS琐碎知识点(持续补充)

    一.字体单位,pt?px?em?rem? pt:磅,一种固定长度的绝对的度量单位,是能够使用测量设备测得的长度,印刷业上经常使用,一般用于页面打印排版. px:屏幕设备上能显示出的最小的一个物理点,这 ...

  9. neutron 多租户隔离的实现以及子网间路由的实现

    1.一个network相当于一个二层网络,使用vxlan 隧道连通所有的CNA节点. 2.一个VPC下有多个network,也就是会分配多个vxlan隧道,这些子网间的路由是通过DVR实现的.DVR就 ...

  10. Android沉浸式状态栏的简单实现

    随着卡片式设计在Android系统的上越来越流行,比如现在早已经烂大街的沉浸式状态栏,几乎所有的主流的APP都支持沉浸式状态栏,如QQ.UC浏览器等等.所以觉得有必要学习一下,找了点资料,总结了一下, ...