prufer 序列 學習筆記

2022-05-01 19:30:10 字數 1253 閱讀 6327

上周五看了一下,發現不是很難,今天再看了一眼,把板題做了,順便看了另外一道(懶得碼了)

其實很簡單,我們定義一顆無根樹的 prufer 序列為,欽定任意乙個點為根(方便確定父子關係),每次從葉子中選出乙個編號最小的點,把它的父親加入到 prufer 序列中,並刪掉該節點。

不難看出,我們最後會有 \(n-2\) 個數,而且可以 \(n\log n\) 求出。並且不同樹的 prufer 序列不會相同。實際上我們也可以做到 \(\theta(n)\) 。大概意思就是指標維護當前編號最小的葉子,然後每次刪點的時候把會立馬加入到序列的父親也跟著刪掉就好了,具體見**。

考慮如何從 prufer 序列轉換成一棵樹。不難看出,乙個點的度數就是 prufer 序列中的出現次數。我們可以先把葉子提出來,每次對於 prufer 序列中的乙個點,葉子節點中編號最小的就是它的兒子。然後刪掉這個兒子,看是否是葉子即可。時間複雜度 \(\theta(n\log n)\)。不過我們也可以做到 \(\theta(n)\),與上面類似。

不難發現的是,對於任意乙個 prufer 序列,我們都可以得到相應的一棵樹。於是,\(n\) 個點的生成樹個數就是 \(n^\) 個。相應的,我們可以推出每個點度數固定時的生成樹個數。

板題傳送門

#include using namespace std;

#define int register int

#define ll long long

#define maxn 5000005

template inline void read (t &t)while (c >= '0' && c <= '9') t *= f;}

template inline void read (t &t,args&... args)

template inline void write (t x)if (x > 9) write (x / 10);putchar (x % 10 + '0');}

ll ans;

int n,m,f[maxn],seq[maxn],deg[maxn];

signed main()

for (int i = 1;i <= n - 2;++ i) ans ^= 1ll * i * seq[i];

} else

for (int i = 1;i <= n - 1;++ i) ans ^= 1ll * i * f[i];

} write (ans),putchar ('\n');

return 0;

}

prufer數列學習筆記

學了一種新姿勢叫prufer數列,可以用來解一些關於無根樹計數的問題。prufer數列是一種無根樹的編碼表示,對於一棵n個節點帶編號的無根樹,對應唯一一串長度為n 2的prufer編碼。1 無根樹轉化為prufer序列。首先定義無根樹中度數為1的節點是葉子節點。找到編號最小的葉子並刪除,序列中新增與...

prufer編碼學習筆記

對於乙個無根樹,他的 prufer 編碼是這樣確定的 那麼,通過給定的無根樹求 prufer 編碼就很簡單了 比如下面這個無根樹,它的 prufer 編碼就是 texttt 這個 prufer 編碼有一些很顯然的性質 首先長度肯定是 n 2 但每個元素可能相同,然後對於每個無根樹,它的 prufer...

prufer序列複習小結

快要省選了。抽點時間複習一下東西 以免漏了一些東西 為了在省選之前覺得自己什麼都會 每一次選擇乙個編號最小,並且度數為1的點 把它刪掉 然後讓他唯一連向的點加入prufer序列 如果只有兩個點就結束 這個的話,你可以理解為有乙個陣列a 表示每乙個數在prufer裡面出現的次數 然後每一次,你就選出p...