码迷,mamicode.com
首页 > 其他好文 > 详细

[HNOI2008]明明的烦恼

时间:2017-12-24 20:10:22      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:stdout   for   can   operator   post   ios   csdn   兴趣   cout   

Description

  自从明明学了树的结构,就对奇怪的树产生了兴趣......给出标号为1到N的点,以及某些点最终的度数,允许在
任意两点间连线,可产生多少棵度数满足要求的树?

Input

  第一行为N(0 < N < = 1000),
接下来N行,第i+1行给出第i个节点的度数Di,如果对度数不要求,则输入-1

Output

  一个整数,表示不同的满足要求的树的个数,无解输出0

Sample Input

3
1
-1
-1

Sample Output

2

HINT

  两棵树分别为1-2-3;1-3-2

该题运用到了树的prufer编码的性质:
  (1)树的prufer编码的实现
        不断 删除树中度数为1的最小序号的点,并输出与其相连的节点的序号  直至树中只有两个节点
  (2)通过观察我们可以发现
        任意一棵n节点的树都可唯一的用长度为n-2的prufer编码表示
        度数为m的节点的序号在prufer编码中出现的次数为m-1
  (3)怎样将prufer编码还原为一棵树??
        从prufer编码的最前端开始扫描节点,设该节点序号为 u ,寻找不在prufer编码的最小序号且没有被标记的节点 v ,连接   u,v,并标记v,将u从prufer编码中删除。扫描下一节点。
该题需要将树转化为prufer编码
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 using namespace std;
  7 struct Big_Num
  8 {
  9   int a[5005],len;
 10   Big_Num()
 11   {}
 12   Big_Num &operator *=(const int &b)
 13   {int i;
 14     for (i=1;i<=len;i++)
 15       a[i]*=b;
 16     for (i=1;i<=len;i++)
 17       a[i+1]+=a[i]/10,a[i]%=10;
 18     int loc=len+1;
 19     while (a[loc])
 20       {
 21     a[loc+1]+=a[loc]/10;
 22     a[loc]%=10;
 23     loc++;
 24       }
 25     len=loc-1;
 26   }
 27   void print()
 28   {int i;
 29     for (i=len;i>=1;i--) printf("%d",a[i]);
 30     cout<<endl;
 31   }
 32 }ans;
 33 int d[1001],du[2001],pri[2001],pre[2001],tot,n,cnt,sum,flag;
 34 bool vis[2001];
 35 int main()
 36 {int i,j;
 37   freopen("tree1.in","r",stdin);
 38   freopen("1005.out","w",stdout);
 39   cin>>n;
 40   flag=0;
 41   for (i=1;i<=n;i++)
 42     {
 43       scanf("%d",&d[i]);
 44       if (d[i]!=-1) cnt++,sum+=d[i]-1;
 45       if (d[i]==0||d[i]==n) flag=1;
 46     }
 47   if (n==1)
 48     {
 49       cout<<1;
 50       return 0;
 51     }
 52   if (n==2)
 53     {
 54       if ((d[1]==0||d[1]>1)||(d[2]==0||d[2]>1))
 55     cout<<0;
 56       else cout<<1;
 57       return 0;
 58     }
 59   if (sum>n-2)
 60     {
 61       cout<<0;
 62       return 0;
 63     }
 64   if (flag)
 65     {
 66       cout<<0;
 67       return 0;
 68     }
 69   for (i=2;i<=n-2;i++)
 70     du[i]++;
 71   for (i=2;i<=n-2-sum;i++)
 72     du[i]--;
 73   for (i=1;i<=n;i++)
 74     if (d[i]!=-1)
 75       {
 76     for (j=2;j<=d[i]-1;j++)
 77       du[j]--;
 78       }
 79   for (i=1;i<=n-2-sum;i++)
 80     du[n-cnt]++;
 81   
 82   for (i=2;i<=2000;i++)
 83     {
 84       if (vis[i]==0)
 85     {
 86       pri[++tot]=i;
 87       pre[i]=i;
 88     }
 89       for (j=1;j<=tot;j++)
 90     {
 91       if (pri[j]*i>2000) break;
 92       vis[i*pri[j]]=1;
 93       pre[i*pri[j]]=pri[j];
 94       if (i%pri[j]==0) break;
 95     }
 96     }
 97   for (i=2000;i>=2;i--)
 98     if (pre[i]!=i)
 99       {
100     du[pre[i]]+=du[i];
101     du[i/pre[i]]+=du[i];
102     du[i]=0;
103       }
104   ans.a[1]=1;ans.len=1;
105   for (i=2;i<=2000;i++)
106     if (du[i]>0)
107       {
108     for (j=1;j<=du[i];j++)
109     ans*=i;
110       }
111   ans.print();
112 }

 

[HNOI2008]明明的烦恼

标签:stdout   for   can   operator   post   ios   csdn   兴趣   cout   

原文地址:http://www.cnblogs.com/Y-E-T-I/p/8098780.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!