Series-Parallel Networks UVA 10253

训练指南写如果一个节点表示并联(串联)则其子节点全部为串联(并联)或者单边这是因为任何一个并联(串联)网络都可以由若干个个串联(并联)网络并联(串联)起来组成,这样计数就保证既无重复,有无遗漏,这道题实际上求的是有n个叶节点而且每个非叶节点有至少俩棵子树的树的个数而且注意子树之间是无序的。

整数划分版本:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string> 
#include <sstream>
#include <utility>   
#include <ctime>
 
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::greater;
using std::endl;

typedef long long LL;

int vec[50];
LL table[50];

LL C(LL n, LL m)
{
	double ret = 1.;
	for(int i = 0; i < m; ++i)
		ret *= n-i;
	for(int i = m; i >= 1; --i)
		ret /= i;
	return LL(ret+0.5);
}

void dfs(int s, int res, int n)
{
	if(res == 0)                            
	{
		LL temp = 1LL;
		for(int i = 1; i <= n-1; ++i)
			temp *= C(table[i]+vec[i]-1, vec[i]);
		table[n] += temp;
		return;
	}
	int lim = min(res, n-1);
	for(int i = s; i <= lim; ++i)
	{
		++vec[i];
		dfs(i, res-i, n);
		--vec[i];
	}
}
        
int main()
{
	table[1] = 1LL;
	for(int i = 2; i <= 30; ++i)
		dfs(1, i, i);
	int n;
	while(scanf("%d", &n), n)
	{
		printf("%lld\n", n == 1? 1LL: table[n]*2LL);
	}
	return 0;
}


递推版本:其中table[i][j]表示有i个叶子节点且根的子树最多有j个叶子节点的树的个数

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string> 
#include <sstream>
#include <utility>   
#include <ctime>
 
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::greater;
using std::endl;

typedef long long LL;

LL C(LL n, LL m)
{
	double ret = 1.;
	for(int i = 0; i < m; ++i)
		ret *= n-i;
	for(int i = m; i >= 1; --i)
		ret /= i;
	return LL(ret+0.5);
}

LL table[50][50];

inline LL fun(int ind)
{
	return table[ind][ind-1];
}

int main()
{
	for(int i = 1; i <= 30; ++i)
	{
		table[i][0] = 0LL;
		table[0][i] = 1LL;
		table[i][1] = 1LL;
	}
	table[0][0] = 1LL;
	for(int i = 1; i <= 30; ++i)
	{
		for(int j = 2; j <= 30; ++j)
			for(int p = 0; p*j <= i; ++p)
				table[i][j] += C(fun(j)+p-1, p)*table[i-j*p][j-1];
	}
	int n;
	while(scanf("%d", &n), n)
	{
		printf("%lld\n", n == 1? 1: fun(n)*2);
	}
	return 0;
}



你可能感兴趣的:(Series-Parallel Networks UVA 10253)