其他分享
首页 > 其他分享> > prufer序列

prufer序列

作者:互联网

目录

\(\operatorname{prufer}\)序列

定义

一种无根树上的数列。

顶点标号的无根树转化而来。且对于一棵确定的无根树,其对应的\(\operatorname{prufer}\)序列也是唯一确定的。


构造

无根树到序列

有两个基本操作:

重复这两个操作,直到整棵树剩下2个节点。

容易知道,我们加入序列的数共有\(n-2\)个,这\(n-2\)个数构成的序列就是\(\operatorname{prufer}\)序列。

举个例子,对于下图这棵树:

挂了没

对它执行上述操作:

那么对于这棵有6个节点的节点标号无根树,我们就得到了长度为4的\(\operatorname{prufer}\)序列\(\{2,3,1,2\}\)

代码实现:

inline void Tree_Prufer() {
	for (ri i=1;i<n;++i) f[i]=read(),++ind[f[i]];
	for (ri i=1,j=1;i<=n-2;++i,++j) {
		while (ind[j]) ++j;
		p[i]=f[j];
		while (i<=n-2 && !(--ind[p[i]]) && p[i]<j) p[i+1]=f[p[i]],++i;
	}
	for (ri i=1;i<=n-2;++i) ans^=(1ll*i*p[i]);
	printf("%lld",ans);
}

序列到无根树

三个基本操作:

显然最后点集中还会剩下2个点( \(n-(n-2)=2\) ),把这两点连一条边。

基本就是上面的逆操作,代码如下:

inline void Prufer_Tree() {
	for (ri i=1;i<=n-2;++i) p[i]=read(),++ind[p[i]];
	p[n-1]=n;
	for (ri i=1,j=1;i<n;++i,++j) {
		while (ind[j]) ++j;
		f[j]=p[i];
		while (i<n && !(--ind[p[i]]) && p[i]<j) f[p[i]]=p[i+1],++i;
	}
	for (ri i=1;i<n;++i) ans^=(1ll*i*f[i]);
	printf("%lld",ans);
}

性质与相关结论

性质:\(\operatorname{prufer}\)序列与无根树唯一确定对应。

结论1:度数为\(d[i]\)的节点恰好会在\(\operatorname{prufer}\)序列中出现\(d[i]-1\)次。

简单证明:

先考虑最简单的情况,该节点度数为1,那么它会被直接删掉,也就是出现的次数为0;

将此思想拓展,若该节点度数 \(d[i]\) 大于1,那么它有边直接相连的节点(除了它的父亲)(这个节点数也就是它的度数)每被删掉一个,它就会在序列中出现一次。所以共出现 \(d[i]-1\) 次。

结论2:\(n\)个节点的完全图的生成树个数为\(n^{n-2}\)。

简单证明:

\(n\)个点的无根树对应的\(\operatorname{prufer}\)序列的长度为\(n-2\),这\(n\)个原来的节点标号均可能在这\(n-2\)个位置上出现,也就是说,有\(n^{n-2}\)种可能的\(\operatorname{prufer}\)序列。每个\(\operatorname{prufer}\)序列都可以对应一棵生成树。

结论3:对于给定度数\(d[i]\)的无根树,它的\(\operatorname{prufer}\)序列有

\[\large \frac{(n-2)!}{\prod_{i=1}^{n}(d[i]-1)!} \]

种情况。

简单证明:

由结论1可得:

\(\Rightarrow\) 求\(d[i]-1\)个\(i\)的可重全排列个数。

*可重全排列:全排列个数 除以 重复元素内部全排列个数


例题待补。

标签:度数,节点,根树,序列,prufer,operatorname
来源: https://www.cnblogs.com/Carlotta/p/15536260.html