zoukankan      html  css  js  c++  java
  • 学习笔记——prufer序列

    prufer序列是什么?

    百度百科这样说:

    Prufer数列是无根树的一种数列。在组合数学中,Prufer数列由有一个对于顶点标过号的树转化来的数列,点数为n的树转化来的Prufer数列长度为n-2。它可以通过简单的迭代方法计算出来。


    与无根树的转换

    1.无根树转prufer序列

    重复以下步骤直至只剩下两个点:

    找到度数为1的且编号最小的节点x,将它所连接的节点加入(prufer)序列一次,然后删掉x

    2.prufer序列转无根树

    准备好一个点集(({1,2,3,4,....,n})

    重复以下步骤直至(prufer)序列为空:

    找到点集中还存在的且在当前的prufer序列中未出现的最小的一个点v,用当前(prufer)序列的第一个数(u),将(u)(v)连边,然后删除(u)(v)

    性质

    • 该序列长度为(n-2)(废话)

    • 一个度数为(d_i)的点会在序列中出现(d_i-1)次(它的度从(d_i)变成1共加入序列了(d_i-1)次)

    • (prufer)序列与无根树一一对应,这意味着求无根树的个数等价于求(prufer)序列的个数,活生生的将树上问题(误)转换为了序列问题


    题目

    1.[HNOI2004]树的计数

    题意:给定一棵树中每个节点的度数(d_i),求满足条件的树的个数,答案不超过(1e17)

    做法:由上面的性质可知,每个点会在(prufer)序列中出现(d_i-1)次,求树的个数等价于求序列个数,那么这就变成了一个多重集排列问题,套用公式可得:

    (ans = frac{(n-2)!}{prod_{i=1}^n(d_i-1)!})

    另外此题需要一些特判,如(Sigma(d_i-1) eq n-2),或者只有一个点,又或者(d_i=0),这里不再赘述(虽然已经说完了

    由于计算过程中可能炸(longlong),需要高精度除法或者分解质因数化除为减

    2.[HNOI2008]明明的烦恼

    题意:同上,如果给定的(d_i=-1),则表示这个点的度数不受限制

    做法:设(cnt)表示(d_i eq-1)的点的个数,(sum)表示(Sigma(d_i-1))(前提是(d_i eq-1)),于是这些点和上题一样满足(假设(d_{1-cnt})( eq -1)的点):

    (p = frac{sum!}{prod_{i=1}^{cnt}(d_i-1)!})

    由于总共有(n-2)个位置,这(sum)个位置的选法有(C_{n-2}^{sum})

    剩下的((n-cnt))个点可以在剩下的((n-2-sum))个位置出现任意次数,即有((n-cnt)^{n-sum-2})种选择

    所以有:

    (ans=C_{n-2}^{sum}*p*(n-cnt)^{n-sum-2})

    化简可得:

    (ans=frac{(n-2)!}{(n-2-sum)!prod(di-1)!}*(n-cnt)^{n-sum-2})

    用第一题的做法做即可,乘法加法要用高精度

  • 相关阅读:
    matlab如何写一个类
    最大稳定极值区域(MSER)检测
    Excel中公式的绝对引用和相对引用单元格
    c++中自增(++)和自减(--)操作符
    C++中的c_str()函数用法
    一些常用的图像数据库
    浅谈C++中指针和引用的区别
    selenium之find_element_by_xpath定位元素
    python selenium使用
    H5页面调用手机扫一扫功能
  • 原文地址:https://www.cnblogs.com/Chtholly/p/11402692.html
Copyright © 2011-2022 走看看