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
这篇博客加深了我对这题的理解。
前边说到相邻序列的三种关系,这篇博客中加了一种讨论
当两节点相邻,但当前节点小于根节点,就代表当前节点是根节点的子节点,要着重注意的是相邻的条件。
但他说的第四条那个等效问题我还不是很明白。以后再回过头来看看。