Uva 10410 Tree Reconstruction

deepwzh發表於2017-01-31

題目大意是根據輸入的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

這篇部落格加深了我對這題的理解。

前邊說到相鄰序列的三種關係,這篇部落格中加了一種討論

當兩節點相鄰,但當前節點小於根節點,就代表當前節點是根節點的子節點,要著重注意的是相鄰的條件。

但他說的第四條那個等效問題我還不是很明白。以後再回過頭來看看。

相關文章