[学习笔记] prufer序列

prufer序列

这个东西很早以前就听说过了,现在来系统地学习一下吧。

感谢 OI Wiki,每次它都能让我看懂,然后我就把他上面的抄下来了

\(\tt prufer\) 序列可以将一个带标号 \(n\) 个节点的树用 \([1,n]\) 中的 \(n-2\) 个整数表示,可以理解为完全图的生成树和数列之间的双射,也正是这个特性它可以用于关于树的组合计数问题上。

如果我们要对树建立 \(\tt prufer\) 序列,那么每次选择一个最小的叶节点然后把他删掉,然后在序列中加入他连向的那个节点,重复 \(n-2\) 次后会剩下两个节点,用堆来维护可以做到 \(O(n\log n)\)

那么怎么用 \(\tt prufer\) 序列构建树呢?首先我们知道最后一定会剩下 \(n\),而且每个点的度数是在序列中的出现次数\(+1\),所以根据 \(\tt prufer\) 序列可以得到每个点的度数,那么使用类似的方法,我们找到编号最小的度数为 \(1\) 的节点,把他和当前考虑到的序列上的点连边,然后度数同时减去 \(1\) 即可,用堆来做同样是 \(O(n\log n)\) 的。

现在我们就能用 \(\tt prufer\) 序列来造毒瘤数据了,下面来看几道例题。

图连通方案数

题目描述

一个 \(n\) 个点 \(m\) 条边的无向图有 \(k\) 个连通块,问有多少种方案添加 \(k-1\) 条边能使他变成一棵树。

这个题目的应用:点这里看

解法

已知第 \(i\) 个连通块的大小为 \(s_i\),现在我们套 \(\tt prufer\) 序列,但是直接连上 \(k-1\) 条边会有点问题,因为每个连通块大小不同,一棵树的方案会和每个连通块连出去的边数有关,那么我们可以设第 \(i\) 个连通块的度数为 \(d_i\) 来表示方案。

对应到 \(\tt prufer\) 序列中就是强制第 \(i\) 个连通块出现了 \(d_i-1\),这个可以直接组合数:

\[{k-2\choose d_1-1,d_2-1...d_n-1}=\frac{(k-2)!}{(d_1-1)!(d_2-1)!...(d_n-1)!} \]

再乘上连通块内部选点的方案数就是:

\[\sum_{0<d_i,\sum d_i=2k-2}\frac{(k-2)!}{(d_1-1)!(d_2-1)!...(d_n-1)!}\times\prod_{i=1}^ks_i^{d_i} \]

这个东西看似无法化简,但是如果你知道 广义二项式定理 的话:

\[(x_1+x_2...+x_n)^k=\sum_{0<y_i,\sum y_i=k}\frac{k!}{y_1!y_2!...y_n!}\times\prod_{i=1}^n x_i^{y_i} \]

那么令 \(x_i=s_i,y_i=d_i-1\),我们就可以直接套公式了:

\[(s_1+s_2...+s_n)^{k-2}\times\prod_{i=1}^k s_i=n^{k-2}\prod_{i=1}^ks_i \]

posted @ 2021-04-07 11:31  C202044zxy  阅读(121)  评论(0编辑  收藏  举报