[BZOJ1005] HNOI2008 obviously troubles

Problem Description

Since obviously learned tree, the tree on the right strange generated interest ...... given numbered 1 to N points, and the final degree certain points, allowing
the connection between any two points may be how many degrees to meet the requirements of the tree was generated?

Input Format

The first behavior N (0 <N <= 1000 ),
the next N rows, row i + 1-Di given degree of node i, if the degree is not required, enter -1

Output Format

An integer representing the number of the tree meet different requirements, no solution outputs 0

Sample input

3
1
-1
-1

Sample Output

2

Sample interpretation

Two trees are 1-2-3; 1-3-2

Resolve

Next we need to use Purfer Sequence.

Purfer Sequence

The unrooted tree constructed in accordance with the following principles of this tree sequence is referred Purfer Sequence. If the tree size is n, then such a sequence of length n-2.

Principle: Each found in the current tree of degree, the minimum number of points 1, will join his father at this point in the sequence, while this point be deleted from the tree

This sequence has a number of properties, such as corresponding to each unique Purfer Sequence unrooted tree. However, we want to use is another very important property:

For each node in the tree \ (I \) , provided the degree of \ (D_i \) , then the \ (I \) in the sequence appears \ (d_i-1 \) times.

With this nature after, look at this question. Suppose we already know the degree of each point, then the number of unrooted tree program to meet the conditions as follows:

\[ans=\frac{(n-2)!}{\prod_{i=1}^{n}(d_i-1)!} \]

This is a formula to be rearranged. But now some point is not limited, and the sequence length only \ (2-n-\) . So, remember:

\[cnt=\sum_{i=1}^n[d_i!=-1]\\sum=\sum_{i=1}^n[d_i!=-1]\times (d_i-1) \]

Then, a program is legitimate in \ (n-2 \) selected positions in the \ (SUM \) a, these positions can be rearranged. The rest position may be \ (n-cnt \) just put points. Program number:

\[ans=C_{n-2}^{sum}\frac{sum!}{\prod_{i=1}^n [d_i!=-1]\times (d_i-1)!}\times (n-cnt)^{n-2-sum} \]

Simplification can be obtained:

\[ans=\frac{(n-2)!}{(n-2-sum)!\times \prod_{i=1}^n [d_i!=-1]\times (d_i-1)!}\times (n-cnt)^{n-2-sum} \]

Of course, one is written so also require high-precision multiplication and division. We can use the prime factorisation, the final answer becomes prime factor multiplied form, then it can be used with high precision by the low-precision calculations.

Note, Purfer Sequence count can solve most of the problems related to the degree of the tree.

PS: the above explanation Purfer Sequence of too simple, can explain For Baidu

Code

#include <iostream>
#include <cstdio>
#define N 1000002
using namespace std;
int n,sum,cnt,i,j,k,d[N],p[N],c[N],num,ans[N],l;
bool vis[N];
int read()
{
	char c=getchar();
	int w=0,f=1;
	while(c<'0'||c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c<='9'&&c>='0'){
		w=w*10+c-'0';
		c=getchar();
	}
	return w*f;
}
void change(int x,int op)
{
	for(int i=1;i<=num;i++){
		while(x%p[i]==0) c[p[i]]+=op,x/=p[i];
	}
}
int main()
{
	n=read();
	for(i=2;i<=1000;i++){
		if(!vis[i]){
			p[++num]=i;
			for(j=i;j<=1000;j+=i) vis[j]=1;
		}
	}
	for(i=1;i<=n;i++){
		d[i]=read();
		if(d[i]!=-1){
			cnt++;sum+=d[i]-1;
			for(j=2;j<=d[i]-1;j++) change(j,-1);
		}
	}
	if(n==1){
		if(d[1]>0) puts("0");
		else puts("1");
		return 0;
	}
	else if(n==2){
		if((d[1]!=1&&d[1]!=-1)||(d[2]!=1&&d[2]!=-1)) puts("0");
		else puts("1");
		return 0;
	}
	for(i=1;i<=n;i++){
		if(d[i]==0||d[i]>=n){
			puts("0");
			return 0;
		}
	}
	for(i=2;i<=n-2;i++) change(i,1);
	for(i=2;i<=n-sum-2;i++) change(i,-1);
	for(i=1;i<=n-sum-2;i++) change(n-cnt,1);
	ans[1]=l=1;
	for(i=2;i<=1000;i++){
		for(j=1;j<=c[i];j++){
			int tmp=0;
			for(k=1;k<=l;k++){
				ans[k]=ans[k]*i+tmp;
				tmp=0;
				if(ans[k]>=10) tmp=ans[k]/10,ans[k]=ans[k]%10;
			}
			while(tmp) ans[++l]=tmp%10,tmp/=10;
		}
	}
	for(i=l;i>=1;i--) printf("%d",ans[i]);
	puts("");
	return 0;
}

Guess you like

Origin www.cnblogs.com/LSlzf/p/12623848.html