zoukankan      html  css  js  c++  java
  • Prufer序列与有根树(森林)计数

    Prufer 序列的构造过程:
     对于一棵有标号无根树,我们每次选择它的所有叶子中标号最小的删去,并将它的父亲的标号加入到一个初始为空的序列末尾,直到剩下两个结点,此时得到的长度为 n-2 的序列即为这棵树的 Prufer 序列。
     对于一个 Prufer 序列,我们每次找到标号最小的没有在序列中出现的点,将它和序列开头的点连边,再将序列开头的那个点从序列中删去,如此循环,最后再在剩下的两个没选过的点之间连边,就可以还原整棵树。
     每棵无根树都对应了一个 Prufer 序列;每个长度为 n-2,元素取值在 1~n 范围内的序列都对应了一棵树,所以不同树的数量为 $ n^{n-2} $。


    根据 Prufer 序列,我们知道 n 个点的有标号无根树的个数是 (n^{n-2})

    我们还可以发现一个性质,如果一个点在树中的度数为 (d_i),那么它会在 Prufer 序列中出现 (d_i-1) 次,那么如果我们限定序列中 (d_i-1) 个位置为 i,剩下 (n-d_i-1) 个位置为除 i 以外的其他数,那么就可以得到 i 的度数恰好为 (d_i) 的树的数量了。也就是:

    [C_{n-2}^{d_i-1} (n-1)^{n-d_i-1} ]

    类似的,我们可以得到确定了每个点的度数 (d_i) 之后的树的数量:

    [frac{(n-2)!}{prod(d_i-1)!} ]


    我们还可以考虑有根树的计数,我们可以在无根树的基础上选一个根,那么方案数为 (n^{n-1}) ,也可以考虑构造一个长度为 n-1 的序列,那么相当于每次剥叶子直到剩下一个根,方案数也是 (n^{n-1})

    然后我们考虑有根树森林计数,我们假设有 n 个点,m 棵树,一种方法是我们先选定 m 个根,然后类似的做一个 Prufer 序列的过程,得到一个长度为 n-m 的序列,我们发现只有最后一个位置是只能取 m 个根之一的,剩下的位置都可以在 1~n 中任意取,所以总的数量是:

    [C_n^m m n^{n-m-1}=C_{n-1}^{m-1} n^{n-m} ]

    还有一种更为简单的方法是:我们建一个虚点 n+1 ,然后构造一棵 n+1 个点的无根树,并假定以 n+1 号点为根,然后把虚点拆掉,它的儿子就会形成若干棵有根树森林,我们只需要保证 n+1 号点的度数恰好为 m 即可。

    所以方案数为:

    [C_{n-1}^{m-1} n^{n-m} ]

    和上面得到的结果是一样的。


    接下来我们考虑不限制有多少棵树的有根树森林。

    可以由上面建虚点的方法直接得到方案数为((n+1)^{n-1})

    也可以枚举有多少个根用二项式定理推导:

    [sum_{m=1}^n C_{n-1}^{m-1} n^{n-m}=(n+1)^{n-1} ]

  • 相关阅读:
    【软工4】:软件工程和文档
    ER模型图工具:PowerDesigner
    【软工3】:软件工程视频知识总结
    【软工2】:软件开发阶段
    【软工1】:软件计划及软件需求
    【机房收费系统 5】:验收总结(思想)
    【机房收费系统 4】:VB获取标准北京时间,免除时间误差
    网络经济与企业管理(一)
    【机房收费系统 3】:文本框输入数字、小数点、退格键
    .NET Framework
  • 原文地址:https://www.cnblogs.com/lishuyu2003/p/13470976.html
Copyright © 2011-2022 走看看