UVA10410 TreeReconstruction 樹重建 (dfs,bfs序的一些性質,以及用棧處理遞歸 )


題意,給你一顆樹的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,大功告成~

學習點:

1.用棧處理遞歸過程。

2.bfs,dfs線性序列的性質。

原來樹形轉線性要用到這些性質

// 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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM