傳送門
這是最後一場基礎訓練啦~看過題解的我居然真的有這種情況=-=
我是真的有些細節沒有想清楚,提交了,竟然過了???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...