1. 程式人生 > 實用技巧 >樹的計數[NOI2013]

樹的計數[NOI2013]

題目描述

我們知道一棵有根樹可以進行深度優先遍歷(DFS)以及廣度優先遍歷(BFS)來生成這棵樹的 DFS 序以及 BFS 序。兩棵不同的樹的 DFS 序有可能相同,並且它們的 BFS 序也有可能相同,例如下面兩棵樹的 DFS 序都是 1 2 4 5 3,BFS 序都是 1 2 3 4 5

現給定一個 DFS 序和 BFS 序,我們想要知道,符合條件的有根樹中,樹的高度的平均值。即,假如共有 \(K\) 棵不同的有根樹具有這組 DFS 序和 BFS 序,且他們的高度分別是 \(h_1,h_2,\cdots,h_K\),那麼請你輸出:

\[\dfrac{h_1+h_2+\cdots +h_K}{K} \]

輸入格式

第一行包含 \(n\) 個正整數 ,表示樹的節點個數。

第二行包含 \(n\) 個正整數,是一個 \(1\dots n\) 的排列,表示樹的 DFS 序。

第三行包含 \(n\) 個正整數,是一個 \(1\dots n\) 的排列,表示樹的 BFS 序。

輸入保證至少存在一棵樹符合給定的兩個序列。

輸出格式

輸出 \(1\) 個實數,四捨五入保留恰好三位小數,表示樹高的平均值。

題解

對於給出的dfs序和bfs序,一定有一種方法給點重新標號,使得bfs序變成 \(1,2,3,\cdots,n\) 這個樣子

以樣例為例:dfs序為 \(1,2,4,5,3\),bfs序為 \(1,2,3,4,5\)

發現深度相同的點,在bfs序中一定是連續一段的,所以原題目可以看作給bfs序進行分段,使得分段後滿足dfs序

樣例中 \(n=5\),有4個分段點

經過觀察,有如下幾個分段的限制條件:

條件一

深度為1的點一定只有一個(根),所以 \(1\) 後面要進行分段。變為 \(1 | 2 3 4 5\)

條件二

\(p[i]\) 表示 \(i\) 在dfs序中在第幾個,如 \(p[3]=5,p[4]=3\)

對於 \(i \in [1, n)\),如果 \(p[i]>p[i+1]\),那麼有如下兩種情況:

(以樣例 \(p[3]>p[4]\) 為例)

得到限制條件:對於 \(i \in [1, n)\)

,如果 \(p[i]>p[i+1]\),那麼 \(i\)\(i+1\) 之間要分段

樣例中,\(3\)\(4\) 之間必須要有分割線,即 \(1|23|45\)

樣例中,只有 \(3\) 滿足 \(p[i]>p[i+1]\),所以已經確定的必須要有的分割線為 \(1|23|45\)

條件三

dfs序為 \(12453\)\(2\) 後一個為 \(4\),所以點 \(4\) 的深度最多比點 \(2\)\(1\)

在bfs序中,這就等價於說 \(2\)\(4\) 之間最多有一條分割線

形式化地,設dfs序陣列為 \(d[N]\),那麼對於 \(i\in [1,n)\),如果 \(d[i]+1<d[i+1]\),那麼在bfs序中 \(d[i]\)\(d[i+1]\) 之間最多有一條分割線

發現在樣例中,\(24\) 連在一起,那麼 \(3\) 要不在 \(2\) 前面,要不在 \(4\) 後面

如果 \(3\)\(2\) 前面,那麼有 \(p[2]>p[3]\),出現條件二的情況,\(2\)\(3\) 之間必須有分割線

如果 \(3\)\(4\) 後面,那麼有 \(p[3]>p[4]\),出現條件二的情況,\(3\)\(4\) 之間必須有分割線

樣例中就有 \(p[3]>p[4]\),所以\(3\)\(4\) 之間必須有分割線

所以可以得出結論:\(2\)\(4\) 之間必定至少有一條 由條件二得出的必須存在的分割線

又因為 \(2\)\(4\) 之間最多有一條分割線,所以 \(2\sim 4\) 之間別的未確定的空隙中就必定是沒有分割線的


以上就是3個分割條件,然後考慮如何實現

先找出所有的必須存在的分割線(條件一,二)

樣例中必須存在的分割線就是 \(1|23|45\)

然後根據條件三,\(2\sim 4\) 之間剩餘的空隙就不能填分割線,這裡也就是 \(2\)\(3\) 之間的那個空隙一定不能填

我們把所有 必須填/必須不填 的分割點打上標記,而可以自由選擇填或不填的就不打標記

對於條件一,二,有必須要填的分割線,把必須要填的地方打上標記,並且讓答案+1(必須多分割出一層)

對於條件三,有必須不填的分割線,把必須不填的地方打上差分標記

然後掃一遍,如果有可以自由選擇填或不填的分割點,就讓答案加上0.5