BFS和DFS的性質 NOI2013 樹的計數

2021-07-14 13:31:35 字數 3141 閱讀 1281

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

現給定乙個 dfs 序和 bfs 序,我們想要知道,符合條件的有根樹中,樹的高度的平均值。即,假如共有

k 棵不同的有根樹具有這組 dfs 序和 bfs 序,且他們的高度分別是 h1

,h2,

…,hk

,那麼請你輸出:h1

+h2+

⋯+hk

k 第一行包含

1 個正整數

n,表示樹的節點個數。

第二行包含

n 個正整數,是乙個 1∼

n的排列,表示樹的 dfs 序。

第三行包含

n 個正整數,是乙個 1∼

n的排列,表示樹的 bfs 序。

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

僅包含

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

input

5 

1 2 4 5 3

1 2 3 4 5

output
3.500
如果輸出檔案的答案與標準輸出的差不超過 10−

3,則將獲得該測試點上的分數,否則不得分。

20% 的測試資料,滿足:n≤

10 ;

40% 的測試資料,滿足:n≤

100 ;

85% 的測試資料,滿足:n≤

2000

;100% 的測試資料,滿足:2≤

n≤200000

時間限制:1s

空間限制:

256mb

樹的高度:一棵有根樹如果只包含乙個根節點,那麼它的高度為

1 。否則,它的高度為根節點的所有子樹的高度的最大值加 1。

對於樹中任意的三個節點 a,

b,c ,如果 a,

b 都是

c 的兒子,則 a,

b在 bfs 序中和 dfs 序中的相對前後位置是一致的,即要麼

a 都在

b的前方,要麼

a 都在

b的後方。

我們將bfs序列改為1…

n ,對應的也修改dfs序的標號。 令p

os[i

] 表示bf

s 序為

i 的節點在df

s序中的位置。

然後我們要做的就會要對bf

s 序分層。

每一種分層對應幾種滿足dfs序的方案呢?

這相當於問子節點到父節點有幾種連法。

在兩種不同連法中,父1,父2,子 的相對順序不同,所以只有一種符合dfs序。

所以一種劃分只對應一棵樹。

然後我們來看看應該應該怎麼分層。

首先,考慮一下同一層的點應該滿足的條件

令這一層的節點為[l

,r]

pos[i

]s[i+

1]i∈

[l,r

) ,這個性質很顯然,因為dfs和bfs都是遍歷乙個節點的領接邊的順序是一樣的。

1號節點必須單獨成層。

我們再來看看df

s 序的性質,假設df

s 序為d[

1]…d

[n]

令x[i

] 表示

i 和i+

1節點之間的分層情況。

特別地,x[

1]=1

顯然de

p[i+

1]≤d

ep[i

] ,但是i+

1 比

i 在深度優先遍歷中先遍歷到,只能說明i+

1和i 不是同一層的。x[

i]=1

那麼x[d

[i]]

+x[d

[i]+

1]+⋯

+x[d

[i+1

]−1]

<=

1 ,也就是d[

i]和d[i

+1] 之間最多分一層,對應了df

s 序的性質,de

p[d[

i+1]

]−de

p[d[

i]]<=

1 ,如果x[

d[i]

],x[

d[i]

+1]⋯

x[d[

i+1]

−1] 直接有任何乙個地方因為上乙個條件分層了,那麼這裡就不能分了。

否則這一段內可以分一層,可以不分層,概率相等,所以我們令x[

d[i]

]=0.5 ,代表這一段的分層情況。

最後求答案就很簡單了an

s=∑i

=1n−

1x[i

]

#include
#include

using

namespace

std;

#define maxn 200000

int a[maxn+10],b[maxn+10],d[maxn+10],pos[maxn+10],g[maxn+10],sta[maxn+10],tp,n;

double x[maxn+10],s[maxn+10],ans=1;

void read(int &x)

}void read()

for(i=1;i<=n;i++)

}void solve()

for(i=1;iif(d[i]1])

}for(i=1;i<=n;i++)

g[i]+=g[i-1];

for(i=1;i<=tp;i++)

if(!g[sta[i]])

x[sta[i]]=0.5;

for(i=1;i<=n;i++)

ans+=x[i];

}int main()

bfs和dfs的特點

一 深度優先搜尋 dfs 的特點是 1 深度優先搜尋法有遞迴以及非遞迴兩種設計方法。一般的,當搜尋深度較小 問題遞迴方式比較明顯時,用遞迴方法設計好,它可以使得程式結構更簡捷易懂。當資料量較大時,由於系統堆疊容量的限制,遞迴容易產生溢位,用非遞迴方法設計比較好。2 深度優先搜尋方法有廣義和狹義兩種理...

dfs和bfs的應用

dfs 能找到可行的路徑,所需時間長,需要標記位置 bfs 能找到最短的路徑,所需空間長,需要出入佇列 兩個搜尋的相同點是都利用了二維陣列的圖,有的時候都用了標記方法。但是dfs,我覺得沒什麼變化,就這樣了。但是bfs,1.可以用stl的queue,但是,沒辦法對付路徑記錄。2.可以用自己寫的結構體...

dfs和bfs的總結

dfs dfs演算法是乙個對連通圖進行遍歷的演算法。它的思想是從乙個被選定的點出發一條路走到底,如果得不到目的解,那就返回到上乙個節點,然後換一條路繼續走到底,直到找到目的解返回或者全部遍歷完返回乙個事先定好的值。dfs一般借用遞迴完成整個演算法的構造。dfs演算法的一般框架經我總結大致為下 int...