码迷,mamicode.com
首页 > Web开发 > 详细

蓝书例题之UVa 10253 Series-Parallel Networks

时间:2019-04-11 01:23:58      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:转移   clu   network   its   设置   有一个   过程   names   name   

挺有趣的一道题
首先转化模型,思路参考蓝书,可得出等同于求共n个叶子,且每个非叶结点至少有两个子结点的无标号树的个数的二倍,设个数为\(f[n]\)
考虑怎么求\(f[n]\),假设有一个\(n\)的整数划分,分别代表每棵子树中的叶节点个数,然后用可重组合,乘法原理和加法原理把\(f[n]\)递推出来
这个过程可以用\(dp\)来完成,设\(g[i][j]\)表示子树中叶结点数量最大值小于等于\(i\),共有\(j\)个叶结点的树的个数,转移时枚举最大的叶结点数量\(i\)和叶结点数量为\(i\)的子树个数\(k\),转移方程如下:
\[g[i][j]=\sum\limits_{k=0}^{ki\leqslant j}\binom{f[i]+k-1}{k}g[i-1][j-ki]\]
然后\(f[i]=g[i-1][i]\)
边界的设置比较神奇,我也不明白,直接把大刘的代码拿过来用了

#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define N 30

ll C(ll n, ll m) {
  double ans = 1;
  for(ll i = n-m+1; i <= n; ++i) ans *= i;
  for(ll i = 1; i <= m; ++i) ans /= i;
  return (ll)(ans+0.5);
}

ll g[35][35], f[35];

int main() {
  f[1] = 1; //三个边界
  for(int i = 0; i <= N; ++i) g[i][0] = 1;
  for(int i = 1; i <= N; ++i) g[i][1] = 1;
  for(int i = 1; i <= N; ++i) {
    for(int j = 1; j <= N; ++j) {
      g[i][j] = 0;
      for(int k = 0; k*i <= j; ++k) g[i][j] += C(f[i]+k-1, k)*g[i-1][j-k*i];
    }
    f[i+1] = g[i][i+1];
  }
  int n;
  while(~scanf("%d", &n) && n) printf("%lld\n", n == 1 ? 1 : 2*f[n]); //特判1,别忘乘以2
  return 0;
}

蓝书例题之UVa 10253 Series-Parallel Networks

标签:转移   clu   network   its   设置   有一个   过程   names   name   

原文地址:https://www.cnblogs.com/dummyummy/p/10686901.html

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