1. 程式人生 > >[HNOI2008]明明的煩惱

[HNOI2008]明明的煩惱

多少 興趣 style n-2 長度 prufer編碼 沒有 rip -s

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編碼 沒時間了,先給個網址http://blog.csdn.net/jeremygjy/article/details/50625228
  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]明明的煩惱