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} ]

  • 相关阅读:
    C#各版本新特性
    ubantu操作积累
    C# System.Net.Http.HttpClient使用说明
    IIS下VUE跳转
    融合主流的技术 分布式中间件+微服务+微架构架构
    论减少代码中return语句的骚操作
    shell脚本--多个代码库批量pull最新master代码
    SpringBoot单元测试
    Qt音视频开发36-USB摄像头解码qcamera方案
    Qt音视频开发35-Onvif图片参数
  • 原文地址:https://www.cnblogs.com/lishuyu2003/p/13470976.html
Copyright © 2011-2022 走看看