UVA10410 树重建 Tree Reconstruction
由于我们只需要确定出父子关系,而一个父亲可能有多个儿子,但一个儿子只能有一个父亲。这启发我们从后往前遍历序列寻找。
我们知道,dfs遍历相比于bfs遍历更能体现父子关系,由此想到我们以dfs序列为核心、bfs序列做辅助来做这道题。
我们回顾dfs和bfs的性质,结合题目描述。对于结点
bfs序列
… 、
dfs序列
… 、
其中,
我们考虑当前处理到结点
我们在dfs序列中从结点v向前遍历,我们找到第一个结点
根据上面的表格,我们可以推断出,
思考可以得到,当
那么当
如果
如果
另外需要注意根结点的特殊处理,因为根结点是不可能有兄弟的。
Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1001;
int n;
int D[maxn],B[maxn];
int bfn[maxn];
vector <int> S[maxn];
int ne[maxn];
void init(){
memset(D,0,sizeof(D));
memset(B,0,sizeof(B));
memset(bfn,0,sizeof(bfn));
memset(ne,0,sizeof(ne));
for(int i=1;i<=1000;++i)S[i].clear();
}
void work(){
for(int i=1;i<=n;++i){
cin>>B[i];
bfn[B[i]]=i;
}
for(int i=1;i<=n;++i){
cin>>D[i];
}
for(int i=n;i>=1;--i){
int v=D[i];
for(int j=i-1;j>=1;--j){
int u=D[j];
if((bfn[u]==bfn[v]-1)&&u<v){
ne[u]=v;
break;
}
if(bfn[u]<=bfn[v]-1){
S[u].push_back(v);
break;
}
}
}
if(!S[D[1]].size())S[D[1]].push_back(D[2]);
for(int i=1;i<=n;++i){
printf("%d:",i);
if(S[i].size()){
for(int t=ne[S[i][0]];t;t=ne[t]){
S[i].push_back(t);
}
}
sort(S[i].begin(),S[i].end());
for(int p=0;p<S[i].size();++p){
printf(" %d",S[i][p]);
}
printf("\n");
}
}
int main(){
while(cin>>n){
init();
work();
}
return 0;
}