【学习笔记】prufer序列

122 篇文章 0 订阅

概述

一个 广泛的 用于树的计数、生成的序列。

→ prufer \rightarrow\text{prufer} prufer 序列

百度百科:

一种生成 p r u f e r \rm{prufer} prufer 序列的方法是迭代删点,直到原图仅剩两个点。对于一棵顶点已经经过编号的树 T T T ,顶点的编号为 1 , 2 , … , n 1,2,\dots,n 1,2,,n ,在第 x x x 步时,移去所有叶子节点(度为 1 1 1 的顶点)中标号最小的顶点和相连的边,并把与它相邻的点的编号加入 p r u f e r \rm{prufer} prufer 序列中,重复以上步骤直到原图仅剩两个顶点。

蒟蒻作者这样说:

举个栗子:这样的树。长得真丑

 4--2--1--6
 |     |
 5     3--7
  • 第一次:移除 5 5 5 ,将 4 4 4 加入序列。
  • 第二次:移除 4 4 4 ,将 2 2 2 加入序列。
  • 第三次:移除 2 2 2 ,将 1 1 1 加入序列。
  • 第四次:移除 6 6 6 ,将 1 1 1 加入序列。
  • 第五次:移除 1 1 1 ,将 3 3 3 加入序列。

所以结果就是 ⟨ 4 , 2 , 1 , 1 , 3 ⟩ \langle 4,2,1,1,3\rangle 4,2,1,1,3

性质

结论一: p r u f e r \rm{prufer} prufer 序列长度为 n − 2 n-2 n2
结论二:一个点出现的次数恰为度数减一

构造的方法有另一种理解。选择一条边,这条边满足其中一个端点度数为 1 1 1 。将这条边的端点中,度数不为 1 1 1 的点加入 prufer \text{prufer} prufer 序列,而后删掉这条边。

在这种理解下,可以认为所有边都被删去了。最后一条边的删除没有加入点罢了。

那么一个度数为 d d d 的点,前 d − 1 d-1 d1 条边删去的时候,都会将其加入 prufer \text{prufer} prufer 序列。最后一次则不会。

而且,这也可以用于证明结论一。

结论三: p r u f e r \rm{prufer} prufer 序列与树一一对应

prufer \text{prufer} prufer 序列 → \rightarrow

假设 prufer \text{prufer} prufer 序列为 ⟨ a 1 , a 2 , a 3 , … , a n − 2 ⟩ \langle a_1,a_2,a_3,\dots,a_{n-2}\rangle a1,a2,a3,,an2

我们从前往后(即按照删去的顺序)考虑。

对于第一条被删掉的边, a 1 a_1 a1 一定是其中一个端点。谁是另一个端点呢?假设是 x x x

由于 x x x 的度数一定是 1 1 1 ,根据 结论二 ,出现次数为 0 0 0 。根据定义, x x x 是最小的。

所以: x x x 是未出现的、编号最小的一个!然后将 x x x a 1 a_1 a1 连边。第一条边就搞定了。

a 1 a_1 a1 的度数明显会变小 1 1 1 a 1 a_1 a1 没有任何使用价值了。所以可以将 a 1 a_1 a1 扔掉——这等价于让 a 1 a_1 a1 的度数减小了 1 1 1 ,因为我们是根据 prufer \text{prufer} prufer 序列中出现的次数来推测度数的。

x x x 呢?以后的选择中一定没有 x x x 了(因为 x x x 的度数是 1 1 1 ,而且已经连了一条边)。以后都不考虑 x x x 。就当他不存在吧!

算法雏形已经有了。

百度百科:

⟨ a 1 , a 2 , … , a n − 2 ⟩ \langle a_1,a_2,\dots,a_{n-2}\rangle a1,a2,,an2 为一棵有 n n n 个节点的树的 prufer \text{prufer} prufer 序列,另建一个集合 G = { 1 , 2 , 3 , … , n } \Bbb G=\{1,2,3,\dots,n\} G={1,2,3,,n} ,找出 G \Bbb G G 中最小的未在 prufer \text{prufer} prufer 序列中出现过的数,将该点与 prufer \text{prufer} prufer 序列中首项连一条边,并将该点和 prufer \text{prufer} prufer 序列首项删除,重复操作 n − 2 n-2 n2 次,将集合中剩余的两个点之间连边即可。

蒟蒻作者这样说:

代码大概长这样:

set<int> G; int cnt[N];
void pruferToTree(int a[],int n){
	for(int i=n-2; i>=1; --i)
		++ cnt[a[i]];
	for(int i=1; i<=n; ++i)
		if(not cnt[i])
			G.insert(i);
	for(int i=1; i<=n-2; ++i){
		int t = *G.begin();
		addEdge(t,a[i]); // 加边的函数 
		G.erase(t);
		if(0 == (-- cnt[a[i]]))
			G.insert(i);
	}
	int x = *G.begin();
	G.erase(x);
	addEdge(x,*G.begin());
	G.clear(); // 清空,为下一次做准备 
}

发现 prufer \text{prufer} prufer 序列可以 唯一 转化为一颗树。所以 prufer \text{prufer} prufer 序列与树是对应的。

实战

树的计数

题目描述
一个 n n n 个点的树,有多少种不同的形态?两种形态不同,当且仅当邻接矩阵不同。

解答
就是 prufer \text{prufer} prufer 序列。每一个数字都不大于 n n n ,共 n − 2 n-2 n2 个数字,共 n n − 2 n^{n-2} nn2 种情况。

树的计数贰

题目描述
有一个 n n n 个点的树。编号为 i i i 的点,度数为 d i d_i di 。不同形态的树有多少种?

解答
还是 prufer \text{prufer} prufer 序列。由于 i i i prufer \text{prufer} prufer序列中恰好出现了 d i − 1 d_i-1 di1 次,共 n − 2 n-2 n2 个数,根据排列组合相关定理,总方案数为 ( n − 2 ) ! ∏ i = 1 n ( d i − 1 ) ! \frac{(n-2)!}{\prod_{i=1}^n (d_i-1)!} i=1n(di1)!(n2)!

树的计数叁

题目描述
n n n 个点的有根树,不同形态的数量?

解答
直接定一个根即可。答案 n n − 2 × n = n n − 1 n^{n-2}\times n=n^{n-1} nn2×n=nn1

城市地铁规划

传送门,这是一道 prufer \text{prufer} prufer 序列和 d p dp dp 结合食用的神奇题目。

链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值