首页 > 代码库 > 【bzoj1211】 HNOI2004—树的计数

【bzoj1211】 HNOI2004—树的计数

http://www.lydsy.com/JudgeOnline/problem.php?id=1211 (题目链接)

题意:一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵。给定n,d1, d2, …, dn,编程需要输出满足d(vi)=di的树的个数。

Solution 
  prufer序列,明明的烦恼简化版。

代码:

// bzoj1211#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<cmath>#include<map>#define inf 2147483640#define LL long long#define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);using namespace std;inline LL getint() {    LL x=0,f=1;char ch=getchar();    while (ch>‘9‘ || ch<‘0‘) {if (ch==‘-‘) f=-1;ch=getchar();}    while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘;ch=getchar();}    return x*f;}const int maxn=200;int d[maxn],a[maxn],np[maxn],n;void pls(int x,int f) {    for (int i=2;i<=x;i++)        if (!np[i]) for (int j=i;j<=x;j*=i) a[i]+=f*x/j;}int main() {    np[1]=1;    for (int i=2;i<=150;i++)        if (!np[i]) for (int j=i*2;j<=150;j+=i) np[j]=1;    scanf("%d",&n);    int sum=0;    if (n==1) {        int x;scanf("%d",&x);        if (!x) printf("1");        else printf("0");        return 0;    }    for (int i=1;i<=n;i++) {        scanf("%d",&d[i]);        if (!d[i]) {printf("0");return 0;}        d[i]--;        sum+=d[i];        pls(d[i],-1);    }    if (sum!=n-2) {printf("0");return 0;}    LL ans=1;    pls(sum,1);    for (int i=2;i<=150;i++)        for (int j=1;j<=a[i];j++) ans*=(LL)i;    printf("%lld",ans);    return 0;}

  

【bzoj1211】 HNOI2004—树的计数