生活随笔
收集整理的這篇文章主要介紹了
PAT甲级题目翻译+答案 AcWing(树)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1004 Counting Leaves (30 分)
題意 :
家庭關系可以用家譜樹來表示,給定一個家譜樹,你的任務是找出其中沒有孩子的成員。 第一行包含一個整數 N 表示樹中結點總數以及一個整數 M 表示非葉子結點數。 為了簡單起見,我們將根結點固定設為 01。 輸出從根結點開始,自上到下,樹的每一層級分別包含多少個葉子節點。
# include <iostream>
# include <cstring>
using namespace std
; const int N
= 110 ; int n
, m
;
int h
[ N
] , e
[ N
] , ne
[ N
] , idx
;
int cnt
[ N
] ;
int max_height
; void add ( int a
, int b
)
{ e
[ idx
] = b
, ne
[ idx
] = h
[ a
] , h
[ a
] = idx
++ ;
} void dfs ( int u
, int height
)
{ if ( h
[ u
] == - 1 ) { max_height
= max ( max_height
, height
) ; cnt
[ height
] ++ ; return ; } for ( int i
= h
[ u
] ; ~ i
; i
= ne
[ i
] ) { dfs ( e
[ i
] , height
+ 1 ) ; }
} int main ( )
{ scanf ( "%d%d" , & n
, & m
) ; memset ( h
, - 1 , sizeof h
) ; int id
, k
, son
; while ( m
-- ) { scanf ( "%d%d" , & id
, & k
) ; while ( k
-- ) { scanf ( "%d" , & son
) ; add ( id
, son
) ; } } dfs ( 1 , 1 ) ; printf ( "%d" , cnt
[ 1 ] ) ; for ( int i
= 2 ; i
<= max_height
; i
++ ) printf ( " %d" , cnt
[ i
] ) ;
}
1020 Tree Traversals (25 分)
題意 :
binary tree二叉樹;postorder and inorder traversal sequences后序遍歷和中序遍歷;level order traversal sequence層序遍歷
思路 :
后序中找到根結點,中序中根結點左邊是左子樹,右邊是右子樹,知道了它們的長度 就可以在后序中找到左右子樹分別的根結點;這樣就可以把整顆樹重建; 用l和r兩個哈希表記錄每個根結點的兩個兒子,也就是兩個新的根結點 從根結點開始bfs,層序遍歷 O(N)O(N) O ( N ) ,前提是所有權值不同;如果權值可能不同,對應的二叉樹就不唯一了有一個地方可以優化,如何找一個位置在中序遍歷中出現的位置,先用哈希表存一下 三個哈希表建二叉樹
語法 :
# include <iostream>
# include <unordered_map>
using namespace std
; const int N
= 40 ; int n
;
int inorder
[ N
] , postorder
[ N
] ;
int q
[ N
] ;
unordered_map
< int , int > l
, r
, pos
; int build ( int il
, int ir
, int pl
, int pr
)
{ int root
= postorder
[ pr
] ; int k
= pos
[ root
] ; if ( k
> il
) l
[ root
] = build ( il
, k
- 1 , pl
, pl
+ ( k
- 1 - il
) ) ; if ( k
< ir
) r
[ root
] = build ( k
+ 1 , ir
, pl
+ ( k
- 1 - il
) + 1 , pr
- 1 ) ; return root
;
} void bfs ( int root
)
{ int hh
= 0 , tt
= 0 ; q
[ 0 ] = root
; while ( hh
<= tt
) { int t
= q
[ hh
++ ] ; if ( l
. count ( t
) ) q
[ ++ tt
] = l
[ t
] ; if ( r
. count ( t
) ) q
[ ++ tt
] = r
[ t
] ; } cout
<< q
[ 0 ] ; for ( int i
= 1 ; i
< n
; i
++ ) cout
<< ' ' << q
[ i
] ; cout
<< endl
;
} int main ( )
{ cin
>> n
; for ( int i
= 0 ; i
< n
; i
++ ) cin
>> postorder
[ i
] ; for ( int i
= 0 ; i
< n
; i
++ ) { cin
>> inorder
[ i
] ; pos
[ inorder
[ i
] ] = i
; } int root
= build ( 0 , n
- 1 , 0 , n
- 1 ) ; bfs ( root
) ; return 0 ;
}
1021 Deepest Root (25 分)
題意 :
acyclic無環的 給一個無向圖(n個點,n-1條邊 ),如果不是樹,輸出圖中連通塊個數,否則,輸出使樹高度最高的所有根結點
思路 :
如果只有一個連通塊,那就是樹 求連通塊的數量,最好寫的算法是 并查集 1s=1081s=10^8 1 s = 1 0 8 ,這道題是2s,可以算2?1082*10^8 2 ? 1 0 8 ,且數據范圍是10410^4 1 0 4 ,所以可以暴力枚舉,把每個點當作根,然后求最大深度O(n)O(n) O ( n ) 如果用bfs來求最大深度,就是求其他所有點到這個點的最短距離,如果用dfs就是求u到葉子結點的最大高度,遞歸求u的所有子結點到葉子結點中的max+1 dfs的話,由于我們存的是無向邊,所以我們從某個邊往下搜的時候,從下面也會往上搜回來,所以我們要記一下當前這個點是從哪個點搜過來的,不要走回頭路
# include <iostream>
# include <vector>
using namespace std
; const int N
= 1e4 + 10 , M
= 2 * N
; int n
;
int h
[ N
] , e
[ M
] , ne
[ M
] , idx
;
int fa
[ N
] ; int find ( int x
)
{ if ( fa
[ x
] != x
) fa
[ x
] = find ( fa
[ x
] ) ; return fa
[ x
] ;
} void add ( int a
, int b
)
{ e
[ idx
] = b
, ne
[ idx
] = h
[ a
] , h
[ a
] = idx
++ ;
} int dfs ( int u
, int father
)
{ int depth
= 0 ; for ( int i
= h
[ u
] ; ~ i
; i
= ne
[ i
] ) { int j
= e
[ i
] ; if ( j
== father
) continue ; depth
= max ( depth
, dfs ( j
, u
) + 1 ) ; } return depth
;
} int main ( )
{ cin
>> n
; for ( int i
= 1 ; i
<= n
; i
++ ) h
[ i
] = - 1 , fa
[ i
] = i
; int k
= n
; for ( int i
= 1 , u
, v
; i
<= n
- 1 && cin
>> u
>> v
; i
++ ) { if ( find ( u
) != find ( v
) ) { k
-- ; fa
[ find ( u
) ] = find ( v
) ; } add ( u
, v
) , add ( v
, u
) ; } if ( k
> 1 ) printf ( "Error: %d components\n" , k
) ; else { vector
< int > nodes
; int max_depth
= - 1 , depth
; for ( int i
= 1 ; i
<= n
; i
++ ) { depth
= dfs ( i
, - 1 ) ; if ( depth
> max_depth
) { max_depth
= depth
; nodes
. clear ( ) ; nodes
. push_back ( i
) ; } else if ( depth
== max_depth
) nodes
. push_back ( i
) ; } for ( auto v
: nodes
) cout
<< v
<< endl
; }
}
1043 Is It a Binary Search Tree (25 分)
題意 :
給一棵樹的先序遍歷,判斷它是否是二叉搜索樹或者鏡像二叉搜索樹,如果是就yes,且輸出這棵樹的后序遍歷,否則就輸出no BST:左子樹嚴格小于,右子樹大于等于
思路 :
我們發現BST的中序遍歷(左子樹,根,右子樹)一定是有序的 因此,我們可以根據所給的前序遍歷得到中序遍歷,所以,問題轉換成了給我們中序遍歷和前序遍歷,問是否是二叉搜索樹 但是還是與前面的題有區別,前面的題保證了樹上每個結點的權值 distinct ,但這里不保證。看下列例子,8出現了2個,但在中序遍歷中我們取的是左邊那個8,因為BST定義左子樹是嚴格小于當前根結點。因此,如果有多個相同值,一定要取第一個 那么什么時候無解呢,進行不下去,構造不成二叉樹,就無解了;那么什么時候會構造不下去呢?在中序序列中找不到這個點就構造不下去了,直接return不合法即可 以上是判斷在BST中是否合法,還要判斷BST的鏡像,鏡像前中序遍歷是從小到大,鏡像后就是從大到小,相當于把整個樹反轉一遍,且注意在中序序列中找個根結點時,如果有多個相同的值,要找最后一個,因為要保證右子樹中都比根結點小,也就是說從后往前找 建樹過程中,如果中序遍歷序列中已經沒有數了,說明建樹完成,成功;根據鏡像與否,找到中序序列中當前根結點的位置,如果找不到,return false;如果能找到,接下來,遞歸建立左子樹和右子樹,如果都返回true,才是建樹成功了;關鍵,在建樹過程中完成了后序遍歷(左子樹,右子樹,根)因此,是在最后將根放入postorder數組中
語法 :
注意這個找k的方式,就可以在循環外繼續使用這個找到的k了
# include <iostream>
# include <algorithm>
using namespace std
; const int N
= 1e3 + 10 ; int n
;
int preorder
[ N
] , inorder
[ N
] ;
int postorder
[ N
] , cnt
; bool build ( int il
, int ir
, int pl
, int pr
, int type
)
{ if ( il
> ir
) return true ; int root
= preorder
[ pl
] ; int k
; if ( ! type
) { for ( k
= il
; k
<= ir
; k
++ ) if ( inorder
[ k
] == root
) break ; if ( k
> ir
) return false ; } else { for ( k
= ir
; k
>= il
; k
-- ) if ( inorder
[ k
] == root
) break ; if ( k
< il
) return false ; } bool ok
= true ; if ( ! build ( il
, k
- 1 , pl
+ 1 , k
- 1 - il
+ pl
+ 1 , type
) ) ok
= false ; if ( ! build ( k
+ 1 , ir
, k
- 1 - il
+ pl
+ 1 + 1 , pr
, type
) ) ok
= false ; postorder
[ cnt
++ ] = root
; return ok
;
} int main ( )
{ cin
>> n
; for ( int i
= 0 ; i
< n
; i
++ ) { cin
>> preorder
[ i
] ; inorder
[ i
] = preorder
[ i
] ; } sort ( inorder
, inorder
+ n
) ; if ( build ( 0 , n
- 1 , 0 , n
- 1 , 0 ) ) { puts ( "YES" ) ; cout
<< postorder
[ 0 ] ; for ( int i
= 1 ; i
< n
; i
++ ) cout
<< ' ' << postorder
[ i
] ; cout
<< endl
; } else { reverse ( inorder
, inorder
+ n
) ; cnt
= 0 ; if ( build ( 0 , n
- 1 , 0 , n
- 1 , 1 ) ) { puts ( "YES" ) ; cout
<< postorder
[ 0 ] ; for ( int i
= 1 ; i
< n
; i
++ ) cout
<< ' ' << postorder
[ i
] ; cout
<< endl
; } else { puts ( "NO" ) ; } }
}
1066 Root of AVL Tree (25 分)
題意 :
給一顆AVL樹(平衡二叉搜索樹)的插入序列,求輸出最后這棵樹的根(保證所有結點的權值不同) 在AVL樹中,任何結點的兩個子樹的高度最多相差1個 如果某個時間,某結點的兩個子樹之間的高度差超過1,則將通過樹旋轉進行重新平衡以恢復此屬性
思路 :
平衡樹涉及到 左旋 和 右旋,它們是對稱的 AVL,本質上還是一個BST(二叉搜索樹),BST是一顆有序的樹,BST本質上維護一個有序序列 ,維護的這個序列就是這個BST的中序遍歷 左旋和右旋目的是為了讓這棵樹平衡,但它不能打破這個序列,因此,它們只會改變這棵樹的結構,不會改變這棵樹的中序遍歷 , 右旋就是把B變成根結點,把A變成B的右孩子,把B原先的右孩子E補償給A變成A的左孩子;左旋就是反過來 AVL就是插入后分情況左旋還是右旋
AVL樹詳解: AVL樹,即平衡二叉搜索樹,當一顆二叉搜索樹的左右子樹高度相差(平衡因子)小于等于1時,我們稱其為平衡二叉搜索樹 當一顆二叉搜索樹在插入數據時平衡被打破,我們需要手動調整樹的結點使其重新滿足平衡二叉搜索樹的性質 平衡二叉樹的基本操作: 平衡二叉搜索樹的操作有兩種:左旋和右旋
不論右旋還是左旋,本質就是將即將被旋轉成為根結點的點記錄,然后如果是左旋,將原先根結點的右兒子更新為新根結點的左兒子,
平衡二叉樹的失衡情形以及對應解決方法: 使平衡二叉樹失去平衡主要有四種情形: 1.左子樹比右子樹高2 -左子樹的左子樹比左子樹的右子樹高1 -左子樹的右子樹比左子樹的左子樹高1 2.右子樹比左子樹高2 -右子樹的左子樹比右子樹的右子樹高1 -右子樹的右子樹比右子樹的左子樹高1
上面四種情況從上往下分別對應圖中的1,3,4,2
回到本題中 :
update函數更新 結點的高度,使用遞歸的方法 每次插入一個點,首先根據BST的規則遞歸找到位置插入成為一個葉結點,然后回溯,每次回溯回來平衡這棵樹,如果在當前這個根結點不平衡,看是兩種中的哪種情況,
# include <iostream>
using namespace std
; const int N
= 30 ; int l
[ N
] , r
[ N
] , v
[ N
] , h
[ N
] , idx
; int get_balance ( int u
)
{ return h
[ l
[ u
] ] - h
[ r
[ u
] ] ;
} void update ( int u
)
{ h
[ u
] = max ( h
[ l
[ u
] ] , h
[ r
[ u
] ] ) + 1 ;
} void R ( int & u
)
{ int p
= l
[ u
] ; l
[ u
] = r
[ p
] , r
[ p
] = u
; update ( u
) , update ( p
) ; u
= p
;
} void L ( int & u
)
{ int p
= r
[ u
] ; r
[ u
] = l
[ p
] , l
[ p
] = u
; update ( u
) , update ( p
) ; u
= p
;
} void insert ( int & u
, int w
)
{ if ( ! u
) u
= ++ idx
, v
[ idx
] = w
; else if ( w
< v
[ u
] ) { insert ( l
[ u
] , w
) ; if ( get_balance ( u
) == 2 ) { if ( get_balance ( l
[ u
] ) == 1 ) R ( u
) ; else L ( l
[ u
] ) , R ( u
) ; } } else { insert ( r
[ u
] , w
) ; if ( get_balance ( u
) == - 2 ) { if ( get_balance ( r
[ u
] ) == - 1 ) L ( u
) ; else R ( r
[ u
] ) , L ( u
) ; } } update ( u
) ;
} int main ( )
{ int n
, root
= 0 ; scanf ( "%d" , & n
) ; int w
; while ( n
-- ) { scanf ( "%d" , & w
) ; insert ( root
, w
) ; } printf ( "%d" , v
[ root
] ) ;
}
1079 Total Sales of Supply Chain (25 分)
題意 :
結點為0-(n-1)的樹,給出根結點每件 商品價格p,溢價為r,即每一層增加r%。只有葉子結點能賺錢,輸入葉子結點時給出每個葉子結點賣出的件數,求總共價格
思路 :
就是遍歷每個葉子結點 ,答案累加當前葉子結點賣出件數c[i]c[i] c [ i ] 乘根結點價格P,再乘溢價的層數次方,算層數,用遞歸加上記憶化 ;因此輸入時要記錄每個點的父節點 遞歸時如何判斷根結點 呢?將父節點數組初始化為-1,父節點為-1的就是根結點了
語法 :
# include <iostream>
# include <cstring>
# include <cmath>
using namespace std
; const int N
= 1e5 + 10 ; int n
;
double P
, R
;
int p
[ N
] , f
[ N
] , c
[ N
] ; int dfs ( int u
)
{ if ( f
[ u
] ) return f
[ u
] ; if ( p
[ u
] == - 1 ) return f
[ u
] = 0 ; return f
[ u
] = 1 + dfs ( p
[ u
] ) ;
} int main ( )
{ scanf ( "%d%lf%lf" , & n
, & P
, & R
) ; memset ( p
, - 1 , sizeof p
) ; for ( int i
= 0 ; i
< n
; i
++ ) { int k
; scanf ( "%d" , & k
) ; for ( int j
= 0 ; j
< k
; j
++ ) { int son
; scanf ( "%d" , & son
) ; p
[ son
] = i
; } if ( ! k
) scanf ( "%d" , & c
[ i
] ) ; } double res
= 0 ; for ( int i
= 0 ; i
< n
; i
++ ) if ( c
[ i
] ) res
+= c
[ i
] * P
* pow ( 1 + R
/ 100 , dfs ( i
) ) ; printf ( "%.1lf" , res
) ;
}
1086 Tree Traversals Again (25 分)
題意 :
通過使用棧可以以非遞歸方式實現二叉樹的中序遍歷。 例如,假設遍歷一個如下圖所示的 6 節點的二叉樹(節點編號從 1 到 6)。 則堆棧操作為:push(1); push(2); push(3); pop(); pop(); push(4); pop(); pop(); push(5); push(6); pop(); pop()。 我們可以從此操作序列中生成唯一的二叉樹。 你的任務是給出這棵樹的后序遍歷。
思路 :
若當前操作為push,上次為push,說明當前操作的數是上一個數的左兒子,上次為pop,說明是右兒子 因此,我們需要記錄上一次操作類型(type值為0/1),以及上一次操作的數(變量last,且需要一個堆模擬)
# include <iostream>
# include <stack>
using namespace std
; const int N
= 35 ; int l
[ N
] , r
[ N
] ; void dfs ( int u
, int root
)
{ if ( l
[ u
] ) dfs ( l
[ u
] , root
) ; if ( r
[ u
] ) dfs ( r
[ u
] , root
) ; printf ( "%d" , u
) ; if ( u
!= root
) printf ( " " ) ;
} int main ( )
{ int n
; scanf ( "%d" , & n
) ; stack
< int > stk
; int root
, last
, type
; for ( int i
= 0 ; i
< 2 * n
; i
++ ) {
string s
; cin
>> s
; if ( s
== "Push" ) { int x
; scanf ( "%d" , & x
) ; if ( i
== 0 ) root
= x
; else { if ( type
== 0 ) l
[ last
] = x
; else r
[ last
] = x
; } last
= x
; type
= 0 ; stk
. push ( x
) ; } else { last
= stk
. top ( ) ; stk
. pop ( ) ; type
= 1 ; } } dfs ( root
, root
) ;
}
1090 Highest Price in Supply Chain (25 分)
# include <iostream>
# include <cstring>
# include <cmath>
using namespace std
; const int N
= 1e5 + 10 ; int n
;
double P
, R
;
int root
;
int p
[ N
] , f
[ N
] ; int dfs ( int u
)
{ if ( f
[ u
] ) return f
[ u
] ; if ( u
== root
) return f
[ u
] = 0 ; return f
[ u
] = 1 + dfs ( p
[ u
] ) ;
} int main ( )
{ scanf ( "%d%lf%lf" , & n
, & P
, & R
) ; for ( int i
= 0 , x
; i
< n
&& scanf ( "%d" , & x
) ; i
++ ) { if ( x
== - 1 ) root
= i
; p
[ i
] = x
; } int res
= 0 , cnt
= 0 ; for ( int i
= 0 ; i
< n
; i
++ ) { if ( dfs ( i
) > res
) { res
= dfs ( i
) ; cnt
= 1 ; } else if ( dfs ( i
) == res
) cnt
++ ; } printf ( "%.2lf %d" , P
* pow ( 1 + R
/ 100 , res
) , cnt
) ;
}
1094 The Largest Generation (25 分)
# include <iostream>
# include <cstring>
# include <vector> using namespace std
; const int N
= 110 ; int n
, m
;
bool g
[ N
] [ N
] ;
vector
< int > level
[ N
] ; int main ( )
{ cin
>> n
>> m
; while ( m
-- ) { int id
, k
; cin
>> id
>> k
; while ( k
-- ) { int son
; cin
>> son
; g
[ id
] [ son
] = true ; } } level
[ 1 ] . push_back ( 1 ) ; int l
= 1 ; while ( level
[ l
] . size ( ) ) { for ( auto ver
: level
[ l
] ) for ( int j
= 1 ; j
<= n
; j
++ ) if ( g
[ ver
] [ j
] ) level
[ l
+ 1 ] . push_back ( j
) ; l
++ ; } int k
= 1 ; for ( int i
= 1 ; i
< l
; i
++ ) if ( level
[ i
] . size ( ) > level
[ k
] . size ( ) ) k
= i
; cout
<< level
[ k
] . size ( ) << ' ' << k
<< endl
; return 0 ;
}
1110 Complete Binary Tree (25 分)
題意 :
給定一個樹,請你判斷它是否是完全二叉樹。給出每個結點的左右子結點的編號 如果是完全二叉樹,則輸出 YES 以及最后一個結點的編號。 如果不是,則輸出 NO 以及根結點的編號。
思路 :
完全二叉樹 即 除了最后一層結點之外 其余所有結點左右兒子都是存在的,且最后一層結點必須都排在最左邊 ! 完全二叉樹有一個很好的性質,就是編號 因此,如果告訴我們它是一個完全二叉樹,那么它一定能按照上面的規則恰好存在1-n這個一維數組中;反之,如果不能,那么一定不是 如果是一顆完全二叉樹,1-n中每一個位置應該是沒有空余位置的,且恰好占一個坑 因此,我們按照這個規則去求每個結點的編號,也就是求他在一維數組中的下標,然后看里面的最大值,看最大值與n的關系,如果恰好等于,說明是完全二叉樹
語法 :
由于這里結點編號從0開始,所以要把空的位置制定為-1,所以初始化l和r為-1
# include <iostream>
# include <cstring>
using namespace std
; const int N
= 25 ; int n
;
int l
[ N
] , r
[ N
] ;
bool has_father
[ N
] ;
int maxid
, maxk
; void dfs ( int u
, int k
)
{ if ( u
== - 1 ) return ; if ( k
> maxk
) { maxk
= k
; maxid
= u
; } dfs ( l
[ u
] , k
* 2 ) ; dfs ( r
[ u
] , k
* 2 + 1 ) ;
} int main ( )
{ scanf ( "%d" , & n
) ; memset ( l
, - 1 , sizeof l
) ; memset ( r
, - 1 , sizeof r
) ; string lc
, rc
; for ( int i
= 0 ; i
< n
; i
++ ) { cin
>> lc
>> rc
; if ( lc
!= "-" ) l
[ i
] = stoi ( lc
) , has_father
[ l
[ i
] ] = true ; if ( rc
!= "-" ) r
[ i
] = stoi ( rc
) , has_father
[ r
[ i
] ] = true ; } int root
= 0 ; while ( has_father
[ root
] ) root
++ ; dfs ( root
, 1 ) ; if ( maxk
== n
) printf ( "YES %d" , maxid
) ; else printf ( "NO %d" , root
) ;
}
1102 Invert a Binary Tree (25 分)
題意 :
invert逆置 level-order層序遍歷 in-order traversal sequences中序遍歷 給你每個結點的左右子結點的編號,輸出反轉后二叉樹的層序遍歷序列和中序遍歷序列,每個序列占一行。
思路 :
如何找到根結點?沒有父節點的就是根結點,因此輸入的時候記錄哪些點有父節點 如何反轉二叉樹?先遞歸左右子樹,最后交換左右兒子,由于編號是從0開始,遞歸終止就不能是0了,我們令遞歸終點是-1,因此,要初始化l和r數組為-1 使用bfs進行層序遍歷 使用dfs進行中序遍歷,由于要控制空格格式,因此多傳入一個變量k記錄當前輸出多少數(因此是引用類型!);遞歸終點仍然是-1
語法 :
這里的lc和rc如果用scanf和%c讀入,需要getchar,比較麻煩,輸入多個char的時候還是用cin比較方便 dfs時k必須是引用類型,否則就不能在遞歸中改變k了
# include <cstring>
# include <iostream>
# include <algorithm> using namespace std
; const int N
= 15 ; int n
;
int l
[ N
] , r
[ N
] ;
int q
[ N
] ;
bool has_father
[ N
] ; void dfs_reverse ( int u
)
{ if ( u
== - 1 ) return ; dfs_reverse ( l
[ u
] ) ; dfs_reverse ( r
[ u
] ) ; swap ( l
[ u
] , r
[ u
] ) ;
} void bfs ( int root
)
{ int hh
= 0 , tt
= 0 ; q
[ 0 ] = root
; while ( hh
<= tt
) { int t
= q
[ hh
++ ] ; if ( l
[ t
] != - 1 ) q
[ ++ tt
] = l
[ t
] ; if ( r
[ t
] != - 1 ) q
[ ++ tt
] = r
[ t
] ; } cout
<< q
[ 0 ] ; for ( int i
= 1 ; i
< n
; i
++ ) cout
<< ' ' << q
[ i
] ; cout
<< endl
;
} void dfs ( int u
, int & k
)
{ if ( u
== - 1 ) return ; dfs ( l
[ u
] , k
) ; cout
<< u
; if ( ++ k
!= n
) cout
<< ' ' ; dfs ( r
[ u
] , k
) ;
} int main ( )
{ cin
>> n
; memset ( l
, - 1 , sizeof l
) ; memset ( r
, - 1 , sizeof r
) ; for ( int i
= 0 ; i
< n
; i
++ ) { char lc
, rc
; cin
>> lc
>> rc
; if ( lc
!= '-' ) l
[ i
] = lc
- '0' , has_father
[ l
[ i
] ] = true ; if ( rc
!= '-' ) r
[ i
] = rc
- '0' , has_father
[ r
[ i
] ] = true ; } int root
= 0 ; while ( has_father
[ root
] ) root
++ ; dfs_reverse ( root
) ; bfs ( root
) ; int k
= 0 ; dfs ( root
, k
) ; return 0 ;
}
1106 Lowest Price in Supply Chain (25 分)
題意 :
現在,給定整個銷售網絡,請你計算零售商能達到的最低銷售價格。
思路 :
# include <iostream>
# include <cstring>
# include <cmath> using namespace std
; const int N
= 100010 ; int n
;
double P
, R
;
int p
[ N
] , f
[ N
] ;
bool is_leaf
[ N
] ; int dfs ( int u
)
{ if ( f
[ u
] != - 1 ) return f
[ u
] ; if ( p
[ u
] == - 1 ) return f
[ u
] = 0 ; return f
[ u
] = dfs ( p
[ u
] ) + 1 ;
} int main ( )
{ cin
>> n
>> P
>> R
; memset ( p
, - 1 , sizeof p
) ; for ( int i
= 0 ; i
< n
; i
++ ) { int k
; cin
>> k
; for ( int j
= 0 ; j
< k
; j
++ ) { int son
; cin
>> son
; p
[ son
] = i
; } if ( ! k
) is_leaf
[ i
] = true ; } memset ( f
, - 1 , sizeof f
) ; int res
= N
, cnt
= 0 ; for ( int i
= 0 ; i
< n
; i
++ ) if ( is_leaf
[ i
] ) { if ( res
> dfs ( i
) ) res
= dfs ( i
) , cnt
= 1 ; else if ( res
== dfs ( i
) ) cnt
++ ; } printf ( "%.4lf %d\n" , P
* pow ( 1 + R
/ 100 , res
) , cnt
) ; return 0 ;
}
1130 Infix Expression (25 分)
Infix Expression中綴表達式 給定一個句法二叉樹,請你輸出相應的中綴表達式,并利用括號反映運算符的優先級。
思路 :
模擬樣例可知就是先遞歸處理左右子樹(如果有的話),然后左子樹結果加上中間的加上右子樹,如果兒子結點不是葉子結點的話,就加上左右括號 因此,輸入時要判斷是否是葉子結點
# include <iostream>
using namespace std
; const int N
= 25 ; int n
;
string w
[ N
] ;
int l
[ N
] , r
[ N
] ;
bool st
[ N
] , is_leaf
[ N
] ; string
dfs ( int u
)
{ string left
, right
; if ( l
[ u
] != - 1 ) { left
= dfs ( l
[ u
] ) ; if ( ! is_leaf
[ l
[ u
] ] ) left
= "(" + left
+ ")" ; } if ( r
[ u
] != - 1 ) { right
= dfs ( r
[ u
] ) ; if ( ! is_leaf
[ r
[ u
] ] ) right
= "(" + right
+ ")" ; } return left
+ w
[ u
] + right
;
} int main ( )
{ scanf ( "%d" , & n
) ; for ( int i
= 1 ; i
<= n
; i
++ ) { cin
>> w
[ i
] >> l
[ i
] >> r
[ i
] ; if ( l
[ i
] != - 1 ) st
[ l
[ i
] ] = true ; if ( r
[ i
] != - 1 ) st
[ r
[ i
] ] = true ; if ( l
[ i
] == - 1 && r
[ i
] == - 1 ) is_leaf
[ i
] = true ; } int root
= 1 ; while ( st
[ root
] ) root
++ ; cout
<< dfs ( root
) ;
}
1138 Postorder Traversal (25 分)
題意 :
假設二叉樹上各結點的權值互不相同且都為正整數。給定二叉樹的前序遍歷和中序遍歷,請你輸出二叉樹的后序遍歷的第一個數字。
思路 :
找到第一個遍歷完左子樹和右子樹的結點,就是所要找的最左下角的點,即答案
# include <iostream>
# include <unordered_map>
using namespace std
; const int N
= 5e4 + 10 ; int pre
[ N
] , in
[ N
] ;
int n
;
int post
;
unordered_map
< int , int > pos
; void build ( int il
, int ir
, int pl
, int pr
)
{ int root
= pre
[ pl
] ; int k
= pos
[ root
] ; if ( k
> il
) build ( il
, k
- 1 , pl
+ 1 , pl
+ 1 + k
- 1 - il
) ; if ( k
< ir
) build ( k
+ 1 , ir
, pl
+ 1 + k
- 1 - il
+ 1 , pr
) ; if ( ! post
) post
= root
;
} int main ( )
{ scanf ( "%d" , & n
) ; for ( int i
= 0 ; i
< n
; i
++ ) scanf ( "%d" , & pre
[ i
] ) ; for ( int i
= 0 ; i
< n
; i
++ ) { scanf ( "%d" , & in
[ i
] ) ; pos
[ in
[ i
] ] = i
; } build ( 0 , n
- 1 , 0 , n
- 1 ) ; printf ( "%d" , post
) ;
}
總結
以上是生活随笔 為你收集整理的PAT甲级题目翻译+答案 AcWing(树) 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。