1. 程式人生 > >樹的計數 Prufer序列+Cayley公式

樹的計數 Prufer序列+Cayley公式

htm size fcm targe enum lock 表示 nlog mar

先安利一發。讓我秒懂。。


第一次講這個是在寒假。。。然而當時秦神太巨了導致我這個蒟蒻自閉+頹廢。。。早就忘了這個東西了。。。

結果今天老師留的題中有兩道這種的:Luogu P4981 P4430

然後決定了解一下。。。

一.Prufer序列

Prufer序列,可以用來解一些關於無根樹計數的問題。

Prufer序列是一種無根樹的編碼表示,對於一棵n個節點帶編號的無根樹,對應唯一一串長度為n-1的Prufer編碼,這性質很好。

1.無根樹轉化為Prufer序列

首先定義無根樹中度數為1的節點是葉子節點(顯然)

找到編號最小的葉節點,刪除這個節點,然後與這個葉節點相連的點計入序列,直到這棵樹只剩下兩個節點,一條邊

如下圖的樹對應的Prufer序列就是3,5,1,3

技術分享圖片

具體實現可以用一個set搞定,維護度數為1的節點。復雜度O(nlogn)。

2.Prufer序列轉化為無根樹。

設點集V={1,2,3,...,n},每次取出Prufer序列中最前面的元素u,在V中找到編號最小的沒有在Prufer序列中出現的元素v,給u,v連邊然後從序列中刪除v,最後在V中剩下兩個節點,給它們連邊。最終得到的就是無根樹。

具體實現也可以用一個set,維護Prufer序列中沒有出現的編號。復雜度O(nlogn)。

最後有一個很重要的性質就是Prufer序列中某個編號出現的次數就等於這個編號的節點在無根樹中的度數-1。

還如果不清楚,看下面(以下引用來自朝拜明天19891101)

第一部分:樹編碼成Prufer序列。

樹編碼成Prufer序列的方式是:Prufer序列初始為空。每次從樹上選出一個編號最小的葉子節點,然後將與該葉子節點相鄰的那個節點的編號寫入Prufer序列的末尾,之後從樹上刪掉這個葉子節點。循環這個步驟n-2次,最後得到一個長度為n-2的Prufer序列(此時樹中只有一條邊,我們就不管它了)。

我們以下面這個樹為例。

技術分享圖片

step1:編號最小的葉子節點為3,將與其相連的節點1加到Prufer的末尾,並將3從樹上刪掉,此時Prufer序列為(1),樹變為如下:

技術分享圖片

step2:編號最小的葉子節點為1,將與其相連的節點2加到Prufer末尾,此時Prufer序列為(1,2),並將節點1刪掉,樹變為如下:


技術分享圖片

step3:編號最小的葉子節點為4,將與其相連的節點2加入到Prufer的末尾,此時Prufer序列為(1,2,2),並將節點4刪掉,樹變為如下:

技術分享圖片

此時,結束,我們得到了Prufer序列為(1,2,2)。



第二部分:由Prufer序列得到樹。首先,將每個節點的度數設為1加上該節點在Prufer序列中出現的次數。然後以下循環執行n-2次。第i次循環,選擇此時度數為1的編號最小的節點u,將其與此時Prufer序列的第i個元素v連邊,然後將u和v的度數都減去1。這n-2次執行完之後,僅剩下兩個節點他們的度數都是1,將這兩個點連邊,這樣就得到一個有n-1條邊的樹。

下面,我們以上面的Prufer序列為例還原這個樹。初始的Prufer為(1,2,2),初始的度數為:

技術分享圖片

step1:選擇度數為1的最小編號的節點3與Prufer的第一個元素1連邊,並將3和1的度數都減去1,得到樹和新的度數:

技術分享圖片

技術分享圖片

step2:選擇度數為1的最小節點1和Prufer中的第二個元素2連邊,並將1和2的度數都減去1,得到樹和新的度數:

技術分享圖片

技術分享圖片
step3:選擇度數為1的最小節點4和Prufer中的第三個元素2連邊,並將4和2的度數都減去1,得到樹和新的度數:
技術分享圖片

技術分享圖片

最後,將僅有的度數為1的兩個節點2和5,連邊,得到:

技術分享圖片

那麽,我們知道這些有什麽用呢?看下面

二.Cayley公式

Cayley公式是說,一個無向完全圖有n^(n-2)棵生成樹,通俗的說就是n個節點的帶編號的無根樹有n^(n-2)個。

剛才Prufer有一個很重要的性質:序列與樹是一一對應的

而Prufer序列有n-2項,序列中的每個數都在1到n的範圍內。

所以我們可以直接推出n個點的無向完全圖的生成樹的計數:n^(n-2)

一個有趣的推廣是,n個節點的度依次為D1, D2, …, Dn的無根樹共有 (n-2)! / [ (D1-1)!(D2-1)!..(Dn-1)! ] 個,因為此時Prüfer編碼中的數字i恰好出現Di-1次(上面的結論)。

下面的結論都看不懂,先咕著:(鏈接)

3)n個節點的度依次為D1, D2, …, Dn,令有m個節點度數未知,求有多少種生成樹?(BZOJ1005 明明的煩惱)

令每個已知度數的節點的度數為di,有n個節點,m個節點未知度數,left=(n-2)-(d1-1)-(d2-1)-...-(dk-1)

已知度數的節點可能的組合方式如下

(n-2)!/(d1-1)!/(d2-1)!/.../(dk-1)!/left!

剩余left個位置由未知度數的節點隨意填補,方案數為m^left

於是最後有

ans=(n-2)!/(d1-1)!/(d2-1)!/.../(dk-1)!/left! * m^left

待填之坑:無標號無根樹、有標號有根樹、無標號有根樹的計數。

參見論文 華中師大一附中 趙爽《樹的計數》、南京師範大學附屬中學 顧昱洲《Graphical Enumeration》

n個點的 有標號有根樹的計數:n^(n-2)*n = n^(n-1)

n個點的 無標號有根樹的計數:

技術分享圖片

n個點的 無標號無根樹的計數:an為 n個點的 無標號有根樹的計數。

技術分享圖片

待填之坑:度數有限制時的計數。如烷烴的計數,每個點的度數最大為4。


2019.05.06

樹的計數 Prufer序列+Cayley公式