一個有n個結點的樹,設它的結點分別爲v1, v2, …, vn,已知第i個結點vi的度數爲di,問知足這樣的條件的不一樣的樹有多少棵。給定n,d1, d2, …, dn,編程須要輸出知足d(vi)=di的樹的個數。ios
1211: [HNOI2004]樹的計數
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 2468 Solved: 868Description
一個有n個結點的樹,設它的結點分別爲v1, v2, …, vn,已知第i個結點vi的度數爲di,問知足這樣的條件的不一樣的樹有多少棵。給定n,d1, d2, …, dn,編程須要輸出知足d(vi)=di的樹的個數。ios
Input
第一行是一個正整數n,表示樹有n個結點。第二行有n個數,第i個數表示di,即樹的第i個結點的度數。其中1<=n<=150,輸入數據保證知足條件的樹不超過10^17個。編程
Output
輸出知足條件的樹有多少棵。ide
Sample Input
4
2 1 2 1
Sample Output
2HINT
Source
【分析】spa
無根樹的表示法用prufer數列。【長姿式】code
將樹轉化成Prufer數列的方法
一種生成Prufer序列的方法是迭代刪點,直到原圖僅剩兩個點。對於一棵頂點已經通過編號的樹T,頂點的編號爲{1,2,...,n},在第i步時,移去全部葉子節點(度爲1的頂點)中標號最小的頂點和相連的邊,並把與它相鄰的點的編號加入Prufer序列中,重複以上步驟直到原圖僅剩2個頂點。例子
Prufer數列以上面的樹爲例子,首先在全部葉子節點中編號最小的點是2,和它相鄰的點的編號是3,將3加入序列並刪除編號爲2的點。接下來刪除的點是4,5被加入序列,而後刪除5,1被加入序列,1被刪除,3被加入序列,此時原圖僅剩兩個點(即3和6),Prufer序列構建完成,爲{3,5,1,3}將Prufer數列轉化成樹的方法
設{a1,a2,..an-2}爲一棵有n個節點的樹的Prufer序列,另建一個集合G含有元素{1..n},找出集合中最小的未在Prufer序列中出現過的數,將該點與Prufer序列中首項連一條邊,並將該點和Prufer序列首項刪除,重複操做n-2次,將集合中剩餘的兩個點之間連邊便可。例子仍爲上面的樹,Prufer序列爲{3,5,1,3},開始時G={1,2,3,4,5,6},未出現的編號最小的點是2,將2和3連邊,並刪去Prufer序列首項和G中的2。接下來連的邊爲{4,5},{1,5},{1,3},此時集合G中僅剩3和6,在3和6之間連邊,原樹恢復
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 160 8 #define LL long long 9 10 int d[Maxn],cnt[Maxn]; 11 12 void cal(int x,int y) 13 { 14 for(int i=2;i*i<=x;i++) if(x%i==0) 15 { 16 while(x%i==0) cnt[i]+=y,x/=i; 17 } 18 if(x!=1) cnt[x]+=y; 19 } 20 21 int main() 22 { 23 int n; 24 scanf("%d",&n); 25 for(int i=1;i<=n;i++) scanf("%d",&d[i]); 26 if(n==1) 27 { 28 if(d[1]==0) printf("1\n"); 29 else printf("0\n"); 30 } 31 else 32 { 33 int sum=0; 34 for(int i=1;i<=n;i++) 35 { 36 if(d[i]==0||d[i]>=n) {printf("0\n");return 0;} 37 sum+=(--d[i]); 38 } 39 if(sum!=n-2) printf("0\n"); 40 else 41 { 42 for(int i=1;i<=n;i++) cnt[i]=0; 43 for(int i=2;i<=n-2;i++) cal(i,1); 44 for(int i=1;i<=n;i++) for(int j=2;j<=d[i];j++) cal(j,-1); 45 LL ans=1; 46 for(int i=1;i<=n;i++) while(cnt[i]--) ans=1LL*ans*i; 47 printf("%lld\n",ans); 48 } 49 } 50 return 0; 51 }