题目描述
给定一个有 n(0<n<=1000) n ( 0 < n <= 1000 ) 个节点的树的bfs序列和dfs序列,重建这棵树,输出每个节点的子节点。无论以何种方式,在遍历树时总是先访问其最小的子节点。
题解
最开始,想用递归的方式重建树。但遇到的问题一是分解子bfs序列和子dfs序列比较麻烦,二是确定层数比较难确定。
之后,参考前辈的做法。是用一个栈保存当前节点,通过遍历dfs序列,确定其子节点。需要注意的是,生成bfs和dfs序列时总是先访问最小的节点。所以当前根节点与当前节点的距离为1但当前节点的值小于根节点时,两个节点不应是兄弟关系。而当不小于时,则两节点时兄弟关系。
AC代码
#include <cstdio>
#include <vector>
#include <stack>
using namespace std;
const int maxn = 1000 + 1;
vector<int> ans[maxn];
int pos[maxn];
int main(){
int n;
while(scanf("%d", &n) != EOF){
int x;
for(int i = 1; i<=n; i++){
scanf("%d", &x);
ans[i].clear();
pos[x] = i;
}
int rot;
scanf("%d", &rot);
stack<int> root;
root.push(rot);
for(int i = 1; i<n; ++i){
scanf("%d", &x);
while(1){
int rt = root.top();
if(rt == rot || pos[rt]+1 < pos[x] || (pos[rt]+1 == pos[x] && rt > x)){
ans[rt].push_back(x);
root.push(x);
break;
}
else root.pop();
}
}
for(int i = 1; i<=n; ++i){
printf("%d:", i);
for(int j = 0, k =ans[i].size(); j<k; ++j)
printf(" %d", ans[i][j]);
printf("\n");
}
}
}