Uva 10410 Tree Reconstruction

题目大意是根据输入的dfs,bfs重建一棵树并输出他的节点。

这道题一开始做的时候没什么思路,原先是想的根据dfs,bfs递归求解,但没有想出来。

后来参考网上的思路,找到了这道题解决的关键所在:dfs和bfs得到的序列中有一个共同特点,每一个节点的相邻节点可能是兄弟节点,可能是孩子节点,也可能都不是。问题关键是判断他是什么类型的节点,这样得到的树才唯一。因此解决这道题需要使用一个栈来求解。

根据bfs,我们可以得到节点之间的距离。

如果dfs中两节点相邻,代表他们是兄弟节点或者子节点或者其他。把第一个节点当做根节点,根据bfs序列判断根节点和另一个节点的距离,如果距离为负,代表既不是兄弟节点,也不是子节点;如果距离为正且相邻,代表是兄弟节点;否则是孩子节点。这样对于任何一个新加入的节点,总可以在栈中找到他的根节点。从而计算出结果来。

大体我能理解到这个程度,下边是我的实现代码

 1 #include <cstdio>
 2 #include <vector>
 3 #include <algorithm>
 4 #include <stack>
 5 using namespace std;
 6 const int maxn = 1000 + 10;
 7 int main(){
 8     int n;
 9     vector<int> g[maxn];
10     int pos[maxn];
11     while(~scanf("%d",&n)){
12         for(int i=1;i<=n;i++){
13             int x;
14             scanf("%d",&x);
15             g[i].clear();
16             pos[x] = i;
17         }
18         
19         int root;
20         stack<int> sta;
21         scanf("%d",&root);
22         sta.push(root);
23         for(int i=1;i<n;i++){
24             int x;
25             scanf("%d",&x);
26             while(true){
27                 int u = sta.top();
28                 if(u==root||pos[u]+1 <pos[x])
29                 {
30                     g[u].push_back(x);
31                     sta.push(x);
32                     break;
33                 }
34                 else{
35                     sta.pop();
36                 }
37             }
38         }
39         for(int i=1;i<=n;i++){
40             printf("%d:",i);
41             sort(g[i].begin(),g[i].end());
42             for(int d : g[i]){
43                 printf(" %d",d);
44             }
45             puts("");
46         }
47 
48     }
49     return 0;
50 }

 另外,

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

这篇博客加深了我对这题的理解。

前边说到相邻序列的三种关系,这篇博客中加了一种讨论

当两节点相邻,但当前节点小于根节点,就代表当前节点是根节点的子节点,要着重注意的是相邻的条件。

但他说的第四条那个等效问题我还不是很明白。以后再回过头来看看。

posted @ 2017-01-31 16:05  deepwzh  阅读(835)  评论(1编辑  收藏  举报