1. 程式人生 > 其它 >prufer序列總結

prufer序列總結

prufer 序列

基礎知識

\(prufer\) 序列是一種 \(n\) 個節點的有標號無根樹與 \(n-2\) 的序列的雙射關係

樹轉序列:每次選出編號最小的 葉節點,將其刪去,並將其父親加入序列,直到還剩兩個點
線性構建:

void T_P(){
	for(int i=1;i<n;i++)fa[i]=read(),deg[fa[i]]++;
	for(int i=1,j=1;i<=n-2;i++,j++){
		while(deg[j])j++;
		p[i]=fa[j];
		while(i<=n-2&&(!(--deg[p[i]]))&&p[i]<j)p[i+1]=fa[p[i]],i++;
	}
}

序列轉樹:列舉最小的點,連向序列的第一個元素

void P_T(){
	for(int i=1;i<=n-2;i++)p[i]=read(),deg[p[i]]++;p[n-1]=n;
	for(int i=1,j=1;i<=n-1;i++,j++){
		while(deg[j])j++;
		fa[j]=p[i];
		while(i<n-1&&(!(--deg[p[i]]))&&p[i]<j)fa[p[i]]=p[i+1],i++;
	}
}

prufer序列的性質

  • 由於對映關係唯一,那麼樹的個數由序列的個數決定,於是 \(n\)
    個節點的有標號無根樹個數為 \(n^{n-2}\)
  • 最後剩下的兩個點,一定有一個是編號最大的點
  • 考慮最後剩下的一條邊一定是編號最大點向其父親(或其最大編號的兒子)的連邊,那麼序列裡的剩下 \(n-2\) 個數恰好對應樹裡剩下的邊
  • 一個度數為 \(deg\) 的節點其在 \(prufer\) 序列裡出現 \(deg-1\)

經典例題

P2290 [HNOI2004]樹的計數

考慮由性質可知,對於點 \(i\),在序列中出現 \(deg_i-1\)
序列總長度為 \(n-2\),每個點出現 \(deg_i-1\) 次,相當於多重集的排列,答案即為:\(\frac{n-2}{\prod deg_i-1}\)


CF156D Clues

設每個連通塊點的個數為 \(s_i\),那麼如果這個連通塊向外總度數為 \(d_i\),那麼方案數為 \(s_i^{d_i}\)
那麼對於每個 \(d_i\) 序列,答案為 \(\displaystyle\binom{k-2}{d_1,d_2,...,d_k}\prod s_i^{d_i}\)
發現和多項式定理類似
於是轉化為 \((d_1+d_2+...+d_k)^{k-2}\prod s_i\)
\(n^{k-2}\prod s_i\)


P5454 [THUPC2018]城市地鐵規劃

可以看做揹包模型,將每個點看做價值為 \(f(deg_i)\),體積為 \(deg_i-1\) 的物品去填充體積為 \(n-2\) 的揹包

揹包過程中可以順便記錄轉移,之後用 \(prufer\) 將序列轉化成樹