基環樹的一些基本問題

HL_ZZP發表於2024-09-03

其實沒啥。

主要就兩個

一、求基環樹的最大直徑
二、判環的簡潔辦法

其中第一個問題比較關鍵,是一個非常常用的基環樹森林模型。而且我基環樹雖然寫了7,8道了,寫的卻總是很冗長。基本全靠碼力彌補才勉強不出錯。。最近寫的題目也是調了很久不出來,就是程式碼不夠簡潔導致的。很多細節可以處理的非常的簡潔但是我卻選擇了複雜的思路。

一:

先說關鍵的模型吧。其實就是一個單調佇列的事情。但是我之前沒有想到這個,導致我賽時沒做出來。後面只是弄懂了但是沒有專門來補,所以也沒有系統的整理這方面的東西。現在來整理了,也是因為剛剛好發現這個模型吧。大致就是先把鏈拆開,然後維護單調佇列,我們把價值函式寫出來\(val=s[i]+s[j]+d[j]-d[i]\),其中\(s[i]\)表示以第i個點為根的子樹的深度,\(d[i]\)表示第\(i\)個點在鏈上的位置,其中\(j>i\)。我們可以發現,維護這個東西的最大值,其實就是對於\(j\)維護最大的\(s[i]-d[i]\),當一個位置的\(i_2\)滿足\(s[i_2]-d[i_2]>s[i_1]-d[i_1]\),且\(i_2>i_1\),那麼\(i_2\)就一定比\(i_1\)更優秀,在任何情況下都不可能會選擇\(i_1\)

我剛剛學的那段時間可能能夠一眼看出來吧,因為確實是一個非常明顯的單調性,隨著長度的增加,之前不優秀的不會變的優秀。這個已經夠明顯了。

除此之外,還有樹的直徑的計算,可以直接用dp求最長路,我每次還寫個次長。。導致要花掉挺多精力的。

二:

這個沒有上一個問題關鍵,放個虛擬碼就懂了吧

int dfs_huan(int x)
{
    vis[x]=1;
    return (vis[u[x]]==1)?x:dfs_huan(u[x]);
}

當時看到了還楞了一下,真心挺簡潔。

就這樣吧,這些都是非常基礎的。。我都不知道為什麼要寫這個,就像不知道為什麼我沒想到單調佇列一樣。

相關文章