zoukankan      html  css  js  c++  java
  • 【算法】Prüfer编码 —— HNOI2004树的计数

      的确,如果不知道这个编码的话的确是一脸懵逼。在这里放一篇认为讲的很详细的 BLOG,有关于编码的方式 & 扩展在里面都有所提及。

      欢迎点此进入 --> 大佬的博客

      在这里主要想推导一下最后面的扩展公式是怎么来的。问题:给定一棵树 & 树上各个节点的度数,求有多少棵满足要求的生成树?

      在了解了Prüfer编码之后,我们已经知道编码与生成树是一一对应的关系了,且一个数在Prüfer编号上面出现的次数即为它的度数 - 1;问题转化成为:一个长度为 (n - 2) 的序列中均为范围在 (1) ~ (n)的数字,规定了每个数字出现的次数,问有多少个合法的序列?首先不考虑是否合法,规定排列当中的数字各不相同,这样的排列有 (left ( n - 2 ight )!) 种。但这样明显统计多了,因为当有相同的数字出现时,交换它们之间的相对位置并不会改变排列的实质。于是我们要在此基础之上除以每一种相同数字的排列数 : (prod left ( d[i] - 1 ight )!)。

      所以最后的式子是: (frac{left ( n - 2 ight )!}{prod left ( d[i] - 1  ight )! })

      HNOI2004树的计数就是一道和和上面这个问题一模一样的题,实际上HNOI2008明明的烦恼也是同一道题(实在是不忍吐槽)。不过后者要写高精,我懒……

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 1000
    #define int long long
    int n, d[maxn], cal[maxn];
    int sum, ans = 1, a[maxn];
    
    int read()
    {
        int x = 0, k = 1;
        char c;
        c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    signed main()
    {
        n = read(); cal[0] = 1;
        for(int i = 1; i <= n; i ++) cal[i] = cal[i - 1] * i;
        for(int i = 1; i <= n; i ++)
        {
            d[i] = read(); if(d[i])
            sum += d[i] - 1;
            if(d[i] == 0 && n != 1) { printf("0
    "); return 0; }
            a[i] = cal[d[i] - 1];
        }
        if(sum != n - 2) { printf("0
    "); return 0; }
        sort(a + 1, a + 1 + n);
        int j = 1;
        while(a[j] == 1 && j < n) j ++;
        for(int i = 1; i <= n - 2; i ++)
        {
            ans *= i;
            while(j <= n && !(ans % a[j])) ans /= a[j], j ++;
        }
        printf("%lld
    ", ans);
        return 0;
    }
  • 相关阅读:
    vue换一换功能原型
    一些文章收集
    mint-ui popup自动关闭
    vue 实现二选一列表
    用数组实现矩阵乘法
    表格
    表单
    django项目创建和结构解释
    js操作元素样式
    操作标签属性
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/9096354.html
Copyright © 2011-2022 走看看