題目大意是根據輸入的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
這篇部落格加深了我對這題的理解。
前邊說到相鄰序列的三種關係,這篇部落格中加了一種討論
當兩節點相鄰,但當前節點小於根節點,就代表當前節點是根節點的子節點,要著重注意的是相鄰的條件。
但他說的第四條那個等效問題我還不是很明白。以後再回過頭來看看。