zoukankan      html  css  js  c++  java
  • prufer序列

    $prufer$ 序列

      突然想起来自己还学过这么一个东西...

    定义

      长度为 $n-2$ 的 $prufer$ 序列可以和 $n$ 个节点的有标号无根树形成一一映射;

    构建方法

      每次删去当前编号最小的叶子 $x$,并在序列末尾加入与 $x$ 相连的点的编号;

    还原方法

      1.找出1至n中没有在序列中出现的最小数 $x$。连接 $x$ 与序列首项,以后找最小值时不再考虑$x$,同时删去序列的首项。

      2.重复上述步骤,直到序列用尽;

      3.连接那两个没有作为最小值出现过的点;

    一些性质

      1.对于一个度数为$x$的点,要删去$x-1$个它的相邻点后它才会被删去,所以它在prufer序列中出现的次数就是 $x-1$;

      2.n个点的带标号无根树一共有$n^{n-2}$种;

      3.对于有根树,在无根树的基础上再枚举一个根就好了,所以共有 $n^{n-1}$ 种;

    几个例题

      树的计数:https://www.luogu.org/problem/P2290

      题意概述:已知每个点的度数,求有多少种满足条件的树;

      根据性质1,已经知道了每个点在prufer序列中的出现次数,接下来只要求一个可重排列就好了。

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

      
     1 # include <cstdio>
     2 # include <iostream>
     3 # define R register int
     4 
     5 using namespace std;
     6 
     7 const int N=160;
     8 int n,s;
     9 int d[N];
    10 int v[N];
    11 
    12 void add (int x,int a)
    13 {
    14     for (R i=2;i<=x;++i)
    15         while(x%i==0) v[i]+=a,x/=i;
    16 }
    17 
    18 int main()
    19 {
    20     scanf("%d",&n);
    21     for (R i=1;i<=n;++i)
    22     {
    23         scanf("%d",&d[i]);
    24         if(n!=1&&d[i]==0)
    25         {
    26             printf("0");
    27             return 0;
    28         }
    29         s+=d[i];
    30     }
    31     if(s!=2*(n-1)) { printf("0"); return 0; }
    32     for (R i=1;i<=n-2;++i) add(i,1);
    33     for (R i=1;i<=n;++i)
    34         for (R j=1;j<=d[i]-1;++j)
    35             add(j,-1);
    36     long long ans=1;
    37     for (R i=1;i<=n;++i)
    38         for (R j=1;j<=v[i];++j)
    39             ans=ans*i;
    40     printf("%lld",ans);
    41     return 0;
    42 }
    树的计数

      明明的烦恼:https://www.luogu.org/problem/P2624

      题意概述:有的点知道了度数,有的点不清楚,求有多少种满足条件的树;

      设有 $k$ 个点知道了度数,$n-k$个点不知道, $s$ 为所有已知度数的点出现的次数和。首先在 $n-2$ 个位置中找出 $s$ 个位置来填这些数,未确定的数可以随便填,所以答案就是:

      $inom{n-2}{s}frac{s!}{prod(d_i-1)!}(n-k)^{n-2-s}$

      
     1 // luogu-judger-enable-o2
     2 # include <cstdio>
     3 # include <iostream>
     4 # define R register int
     5 
     6 using namespace std;
     7 
     8 const int N=1005;
     9 int n,s,cnt;
    10 int v[N],d[N];
    11 int ans[100*N];
    12 
    13 void add (int x,int a)
    14 {
    15     for (R i=2;i<=x;++i)
    16         while(x%i==0) x/=i,v[i]+=a;
    17 }
    18 
    19 void write()
    20 {
    21     for (R i=ans[0];i;i--)
    22         printf("%d",ans[i]);
    23 }
    24 
    25 
    26 void mul (int x)
    27 {
    28        for (R i=1;i<=ans[0];++i) ans[i]*=x;
    29     for (R i=1;i<=ans[0]+5;++i)
    30     {
    31         ans[i+1]+=ans[i]/10;
    32         ans[i]%=10;
    33     }
    34     ans[0]+=5;
    35     while(ans[ ans[0] ]==0&&ans[0]) ans[0]--;    
    36 }
    37 
    38 int main()
    39 {
    40     scanf("%d",&n);
    41     for (R i=1;i<=n;++i)
    42     {
    43         scanf("%d",&d[i]);
    44         if(n==1)
    45         {
    46             if(d[1]==0) { printf("1"); return 0; }
    47             else { printf("0"); return 0; }
    48         }
    49         if(d[i]==0&&n!=1) { printf("0"); return 0; }
    50         if(d[i]!=-1) s+=d[i];
    51         else cnt++;
    52     }
    53     if(cnt+s>2*(n-1)) { printf("0"); return 0; }
    54     s=0; for (R i=1;i<=n;++i) if(d[i]!=-1) s+=d[i]-1;
    55     for (R i=2;i<=n-2;++i) add(i,1);
    56     for (R i=2;i<=n-2-s;++i) add(i,-1);
    57     for (R i=1;i<=n;++i)
    58     {
    59         if(d[i]==-1) continue;
    60         for (R j=2;j<=d[i]-1;++j) add(j,-1);
    61     }
    62     ans[0]=1; ans[1]=1;
    63     for (R i=2;i<=n;++i)
    64         for (R j=1;j<=v[i];++j)
    65             mul(i);
    66     for (R i=1;i<=n-2-s;++i)
    67         mul(cnt);
    68     write();
    69     return 0;
    70 }
    明明的烦恼

      数树:https://www.luogu.org/problem/P5206

      先咕着,我就不信NOIP考这题。

    ---shzr

  • 相关阅读:
    Linux操作系统基础(四)保护模式内存管理(2)【转】
    Linux-0.00运行环境搭建【转】
    一个简单多任务内核实例的分析【转】
    makefile中的自动化变量 【转】
    ARM处理器的寄存器,ARM与Thumb状态,7中运行模式 【转】
    Linux中__init、__devinit等内核优化宏【转】
    中断的理解
    linux rtc 接口【转】
    HDU1506 ( Largest Rectangle in a Histogram ) [dp]
    angularJS使用$watch监控数据模型的变化
  • 原文地址:https://www.cnblogs.com/shzr/p/11533360.html
Copyright © 2011-2022 走看看