uva 10410 TreeReconstruction

题意,给你一颗树的bfs序和dfs序,结点编号小的优先历遍,问你可能的一种树形;

输出每个结点的子结点。

注意到以下事实:

(1)dfs序中一个结点的子树结点一定是连续的。

(2)bfs,dfs序中的一个结点u的后续结点一定是u或u的后兄弟结点{v},或u和{v}的后代节点{s}。

(3)如果有后兄弟结点,那么bfs序中u后面紧跟着的一定是第一后兄弟结点v1,

(4)如果有后代结点,那么dfs序中u后面紧跟着的一定是第一个子结点s1。

记结点u的bfs序记为bfs(u),dfs序记为dfs(v);

dfs序中,一个结点u,结点为v满足dfs(v) = dfs(u) + 1,如果bfs(v) = bfs(u)+1 且 v > u;那么v一定可以视作u的第一个后兄弟结点,

如果不成立,那么v是u的子节点,可以推出u是bfs中u所在层的最后一个结点,这时候u没有后兄弟结点,所以后面的结点一定都是他的后代结点,那么v就一定可以等效作u的兄弟结点而不改变bfs,dfs序。

到此,(5)满足bfs(v) = bfs(u)+1 且 v > u条件的v看作是u的第一个后兄弟结点,不满足这个条件的一定不是后兄弟结点,这个可以根据定义可证。

如果v满足(5),根据(1),u以及子树就访问完了,如果v不满足条件且bfs(v)>bfs(u) + 1那么v一定是u的子结点,如果bfs(v)<bfs(u)那么说明v是其父辈结点,而且u的子树已经访问完了。

迭代上述过程,边界条件是root。大功告成~!

// Rey
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000+5;

vector<int> G[maxn];
int pos[maxn];

int main()
{
 //  freopen("in.txt","r",stdin);
   int n;
   int t;
   while(~scanf("%d",&n)&&n){
      for(int i = 1; i <= n; i++)
         scanf("%d",&t), pos[t] = i, G[i].clear();
      int root;
      scanf("%d",&root);
      stack<int> sta;
      sta.push(root);
      for(int i = 1; i < n; i++){
         scanf("%d",&t);
         for(;;) {
            int u = sta.top();
            if( pos[u]+1 < pos[t] ||  (pos[u]+1 == pos[t] && u > t) || u == root  ) {
               G[u].push_back(t);
               sta.push(t);
               break;
            }else {
               sta.pop();
            }
         }

      }
      for(int i = 1; i <= n; i++) {
         printf("%d:",i);
         for(int j = 0, sz =  G[i].size(); j < sz; j++)
            printf(" %d",G[i][j]);
         puts("");
      }
   }
   return 0;
}

PS:写博客真是可以很好的锻炼自己的表达能力,又能梳理以前的思路。

时间: 2024-10-12 22:22:42

uva 10410 TreeReconstruction的相关文章

uva 10410 - Tree Reconstruction(栈)

题目链接:uva 10410 - Tree Reconstruction 题目大意:给定一个树的BFS和DFS,求这棵树. 解题思路:用栈维护即可.对应BFS序列映射出了每个节点和根节点的距离,遍历dfs序列,对当前节点和栈顶节点比较,如果该节点距离根节点更远,则说明该节点为栈顶节点个孩子节点,则记录后将节点放入栈中.否则弹掉栈顶元素继续比较.需要注意一点,即当元素与栈顶元素的距离值大1的时候要视为相等,因为它们属于兄弟节点 #include <cstdio> #include <cst

UVA 10410 - Tree Reconstruction(树)

UVA 10410 - Tree Reconstruction 题目链接 题意:给定一个树的dfs序列和bfs序列,求出这颗树 思路:拿dfs的序列,分成若干段,每一段相当一个子树,这样就可以利用bfs的序列去将dfs的序列分段,然后利用一个队列去存放每一段,不断求出子树即可.一开始以为parse tree一定是二叉树,原来不一定啊. 代码: #include <cstdio> #include <cstring> #include <vector> #include

UVA - 10410 Tree Reconstruction

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 yo

UVA - 10410 Tree Reconstruction (树重建)

题意:给定一个树的bfs和dfs序列,升序输出每个结点的子结点列表. 分析:因为建树不唯一,假定若bfs[u] = bfs[v] + 1,则u是v的兄弟结点,否则是孩子结点.用栈维护. #pragma comment(linker, "/STACK:102400000, 102400000") #include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #in

UVA - 10410 Tree Reconstruction (根据dfs序和bfs序恢复一颗树)

题意: 分析: 这题一开始完全没有思路, 一直没有找出规律. 参考了http://www.cnblogs.com/Wade-/p/6358859.html 和 http://www.cnblogs.com/jerryRey/p/4622927.html 在dfs序列中,相邻的两个结点u,v之间(dfs_pos(u) + 1 =  dfs_pos(v)),有父子,兄弟,其他3种关系. 父子关系:在bfs中u,v并不是相邻, bfs_pos(v) > bfs_pos(u) , 那么u为v父亲, v为

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

Tree Reconstruction UVA - 10410

这题是真的..不会.我的疑惑点主要在于两个相邻dfs数关系的多样性,因此中间我一直想枚举暴搜,发现不会写代码.然后注意到遍历一定是从小到大的,又不会利用这个性质..总之心态彻底被搞崩了,主要还是太菜. 题目描述:https://vjudge.net/problem/UVA-10410 网上比较详细的解释:https://www.cnblogs.com/jerryRey/p/4622927.html 核心思想主要是在等效吧,在dfs序与bfs序中同时相邻的情况中,兄弟关系与父子关系是等效的,此时就

UVa10410代码

这里就不加太多的注释了,想一想就能明白代码的目的 // UVa 10410 #include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <stack> using namespace std; const int maxn = 1000 + 5; vector<int> node[maxn]; int pos[maxn]; in

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d