prufer序列

来源:互联网 发布:08总决赛皮尔斯数据 编辑:程序博客网 时间:2024/04/25 15:03

给一棵树,它的prufer序列由一下步骤得到:

(1)选择度数为1的编号最小的点,把它删掉并把和它相连的点加入序列
(2)重复第一步直到剩下两个点

prufer序列的性质:

长度为n-2,记每个点的度数为di,那么每个点都会在prufer序列中出现di-1次

那么prufer序列有什么用呢?很显然每棵不同的树都对应一个不同的prufer序列,那么当我们遇到一些需要计算不同的树的个数时就可以把问题转化成组合数学计算啦

bzoj1005代码:

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#include<string>#include<iomanip>#include<vector>#include<set>#include<map>#include<queue>using namespace std;typedef long long LL;typedef unsigned long long ULL;#define rep(i,k,n) for(int i=(k);i<=(n);i++)#define rep0(i,n) for(int i=0;i<(n);i++)#define red(i,k,n) for(int i=(k);i>=(n);i--)#define sqr(x) ((x)*(x))#define clr(x,y) memset((x),(y),sizeof(x))#define pb push_back#define mod 1000000007int n,m,pcnt,p[2000],a[1010],b[1010],d[1010];bool vis[1010];const int maxn=3010;struct bign{    int len,s[maxn];    bign()    {        memset(s,0,sizeof(s));        len=1;    }    bign(int num){*this=num;}    bign(const char *num){*this=num;}    bign operator = (const int num)    {        if(num==0)        {            len=1;            memset(s,0,sizeof(s));            return *this;        }        char s[maxn];        sprintf(s,"%d",num);        *this=s;        return *this;    }    bign operator = (const char *num)    {        for(int i=0;num[i]=='0';num++);        len=strlen(num);        for(int i=0;i<len;i++)s[i]=num[len-i-1]-'0';        return *this;    }    void clean()    {        while(len>1&&!s[len-1])len--;    }    bign operator *(const bign &b)    {        bign c;        c.len=len+b.len;        for(int i=0;i<len;i++)        {            for(int j=0;j<b.len;j++)            {                c.s[i+j]+=s[i]*b.s[j];            }        }        for(int i=0;i<c.len;i++)        {            c.s[i+1]+=c.s[i]/10;            c.s[i]%=10;        }        c.clean();        return c;    }    string str() const    {        string res="";        for(int i=0;i<len;i++)res=char(s[i]+'0')+res;        return res;    }};ostream& operator << (ostream &out,const bign &x){    out<<x.str();    return out;}bign quipow(bign x,int k){    bign ret=1;    while(k)    {        if(k&1)ret=ret*x;        x=x*x;        k>>=1;    }    return ret;}int main(){    pcnt=0;    for(int i=2;i<=1000;i++)    {        if(!vis[i])p[++pcnt]=i;        for(int j=1;j<=pcnt && i*p[j]<=1000;j++)        {            vis[i*p[j]]=1;            a[i*p[j]]=p[j];            if(i%p[j]==0)break;        }    }    scanf("%d",&n);    m=0;    rep(i,1,n)    {        scanf("%d",&d[m+1]);        if(d[m+1]!=-1)m++;    }    if(n<=2)    {        if(n==1)puts(d[1]>0?"0":"1");        else if(n==2)        {            bool flag=0;            rep(i,1,m)if(d[m]!=1)flag=1;            puts(flag?"0":"1");        }        return 0;    }    d[m+1]=n-2;    rep(i,1,m)d[m+1]-=d[i]-1;    if(d[m+1]<0)    {        puts("0");        return 0;    }    rep(i,2,n-2)b[i]++;    rep(i,1,m)rep(j,2,d[i]-1)b[j]--;    rep(i,2,d[m+1])b[i]--;    bign ans=1;    red(i,n-2,2)    {        if(!vis[i])ans=ans*quipow(i,b[i]);        else        {            b[i/a[i]]+=b[i];            b[a[i]]+=b[i];        }    }    ans=ans*quipow(n-m,d[m+1]);    cout<<ans<<endl;    return 0;}
0 0