2020牛客寒假演算法基礎集訓營6 B題(基環樹)

2021-10-02 21:25:54 字數 1609 閱讀 4556

傳送門

這是最後一場基礎訓練啦~看過題解的我居然真的有這種情況=-=

我是真的有些細節沒有想清楚,提交了,竟然過了???emmm

我驚了=-=

這個題目時乙個關於基環樹的題目啦,記憶化搜尋可以解決(不然會超時qaq)

當初比賽一看到這個題目的時候腦海裡瞬間想的是兩次dfs求樹的直徑(該打,不看清題目就寫的痛苦太難受了)

後來還是出題人在廣播裡左強調,右強調,我才=-=又仔細看了好幾遍題目,題目給的是有向圖,可以有自環(我還傻乎乎的求樹的直徑,四不四傻!)

題目要求輸出最長的簡單路徑上面的結點個數=-=

每個結點的出度均為1(這裡我們可以得到這是基環內向樹,如果每個結點點的入度為1的話,那就是基環外向樹),我們可以先處理環的部分,先處理每個環有多少個結點=-=

基環樹有一些這樣的特徵:

構成環的每個結點都是樹根噢,它下面都連著一顆小樹~

沿著乙個結點走下去,一定可以走到環~

所以我們的解題思路就是~

首先處理環部分,把構成環部分的結點個數算出來,然後dfs記憶化搜尋最長的路徑就可以啦~

那麼問題來啦,我們怎麼知道哪些是環部分呢,這就需要用到上面的結論啦,就是沿著乙個結點走下去,一定可以走到環的~

在這裡解釋一下開的陣列的含義:

int a[n];//記錄出度的結點

int vis[n];//記錄是否訪問過

int s[n];//小tips,s[0]記錄當前訪問的結點個數,之後的s[1],s[2]…記錄訪問結點的順序,儲存結點的序號

int ins[n];//記錄當前環的結點是否訪問過,與vis用法記錄相反

int siz[n];//預處理部分記錄環的大小,dfs部分記錄最長路徑的結點個數~

dfs記憶化搜尋有了前面的處理部分,這部分就很好寫啦~~~

上**啦~

#include

using

namespace std;

const

int n =

1e6+10;

int n;

int a[n]

;int vis[n]

;int s[n]

;int ins[n]

;int siz[n]

;int

dfs(

int x)

return siz[x]=1

+dfs

(a[x]);

}int

main()

int i, j, k, h;

for(

int i =

1; i <= n; i++)if

(ins[j]

)while

(k != j);do

while

(k != j);}

while

(s[0])

}}for(i =

1, h =

0; i <= n; i++

) cout << h << endl;

return0;

}

下次補補樹的直徑的部落格~

2020牛客寒假演算法基礎集訓營

長期更新,補完為止 2 g 判正誤 題意 t組資料。判斷a d b e c f是否等於g。1e9 a,b,c,g 1e9,0 d,e,f 1e9。保證不會出現指數和底數同為 0 的情況。思路 硬算會tle或mle。快速冪取模,為了增加過題概率,多取幾個模數判斷。includeusing namesp...

2020牛客寒假演算法基礎集訓營1

找規律,推公式 三角形個數為2 m n m n m 1 n 1 2 m n mn m 1 n 1 2 m n mn m 1 n 1 include include include include using namespace std typedef long long ll const int m...

2020牛客寒假演算法基礎集訓營1

h題 突然發現h題可以用好多種方法做的。方法一 雙指標,維護乙個修改次數小於等於k的區間 include using namespace std typedef long long ll const int mod 1e9 7 const int n 1e5 5 const int inf 0x3f...