UVa 10253 Series-Parallel Networks

《训练指南》中的第二种算法,其实本质上就是个背包。d[i][j]表示,在子树的节点数最大为i的情况下,j个节点的解。当之前的i-1,i-2,....0的结果都已知的时候,d[i][j]自然可根据下式求解:

d[i][j]=sum{C(f(i)+p-1,p)*d[i-1][j-p*i] | p*i<=j}

其中f(i)表示恰好有i个节点的子树的数量。而C(f(i)+p-1,p)则表示有p棵i节点子树形成的组合数。然后运用乘法原理,剩余的节点数为j-p*i且包含的子树最多只有i-1个节点。继而从i=2时开始遍历,将所有的d[i][j]求出,而f(i)=d[i-1][i]。最后的解f(n)自然等于d[n-1][n]。

还要注意的一点是边界的问题。当d[i][j]中的j=0时,则d[i][0]=1,这与求解背包时的边界相似。d[0][1]=1,表示叶子节点。而其他的d[0][i]则都为0,因为有i(i>1)个节点,但没有子树的最大节点数为0,显然是不可能的。最后,在输出结果时,f(1)始终为1,但其他的f(i)要乘以2,因为正如书中所说,根节点为并联节点或串联节点将决定两个不同的序列。

注:关于组合数的求解为什么能这样做,希望有高手能解答!

#include <iostream>
#include <cstdio>
#define MAX 30+2
using namespace std;

long long d[MAX][MAX];
long long f[MAX];
long long C(long long n,long long m)//求解组合数C(n,m)
{
    double ans=1;
    for(int i=0;i<m;++i) ans*=n-i;
    for(int i=1;i<=m;++i) ans/=i;
    return (long long)(ans+0.5);

}

int main()
{
    //freopen("data.txt","r",stdin);
    for(int i=0;i<MAX;++i) d[i][0]=d[1][i]=1;//注意边界
    for(int i=2;i<MAX;++i) d[0][i]=0;
    d[0][1]=1;
    for(int i=2;i<MAX;++i){
        f[i]=d[i-1][i];
        for(int j=1;j<i;++j) d[i][j]=d[i-1][j];//最大子树的节点数大于总节点数,则继承
        for(int j=i;j<MAX;++j)
        for(int p=0;p*i<=j;++p)
            d[i][j]+=C(f[i]+p-1,p)*d[i-1][j-p*i];
    }
    f[1]=1;
    for(int i=2;i<MAX;++i) f[i]*=2;//修改f(i)

    int N;
    while(cin>>N&&N){
        cout<<f[N]<<endl;
    }

    return 0;
}
时间: 2024-10-05 09:53:40

UVa 10253 Series-Parallel Networks的相关文章

UVA 10253 - Series-Parallel Networks(数论+计数问题+递推)

题目链接:10253 - Series-Parallel Networks 白书的例题. 这题也是需要把问题进行转化,一个并联可以分为几个串联,然后串联可以分成边. 如此一来,最后叶子结点种数会是n,问题转化为去分配叶子结点,使得总和为n. 书上有两种方法,一种直接去递归,利用组合数学的方式去计算答案. 一种是推出递推式: 设dp[i][j]为一共j个叶子结点的树,子树的叶子最多的为i个的情况.然后对于一颗树,枚举恰好包含i个叶子的子树为p棵,那么相当于从f[i]颗树中选出p棵树的方案数,是可重

UVa 10253 (组合数 递推) Series-Parallel Networks

<训练之南>上的例题难度真心不小,勉强能看懂解析,其思路实在是意想不到. 题目虽然说得千奇百怪,但最终还是要转化成我们熟悉的东西. 经过书上的神分析,最终将所求变为: 共n个叶子,每个非叶节点至少有两个子节点的 树的个数f(n).最终输出2 × f(n) 首先可以枚举一下根节点的子树的叶子个数,对于有i个叶子的子树,共有f(i)种, 设d(i, j)表示每棵子树最多有i个叶节点,一共有j个叶节点的方案数. 所求答案为d(n-1, n) 假设恰好有i个叶子的子树有p棵,因为每个子树互相独立,所以

蓝书例题之UVa 10253 Series-Parallel Networks

挺有趣的一道题 首先转化模型,思路参考蓝书,可得出等同于求共n个叶子,且每个非叶结点至少有两个子结点的无标号树的个数的二倍,设个数为\(f[n]\) 考虑怎么求\(f[n]\),假设有一个\(n\)的整数划分,分别代表每棵子树中的叶节点个数,然后用可重组合,乘法原理和加法原理把\(f[n]\)递推出来 这个过程可以用\(dp\)来完成,设\(g[i][j]\)表示子树中叶结点数量最大值小于等于\(i\),共有\(j\)个叶结点的树的个数,转移时枚举最大的叶结点数量\(i\)和叶结点数量为\(i\

UVA 10253 Seris-Parallel Networks

https://vjudge.net/problem/UVA-10253 题目 串并联网络有两个端点,一个叫源,一个叫汇,递归定义如下. (1)一条单独的边是串并联网络. (2)若G1和G2是串并联网络,把他们的源和汇分别接在一起也能得到串并联网络. (3)若G1和G2是串并联网络,把G1的汇和G2的源并在一起也能得到串并联网络. 其中规则2说的是并联,规则3说的是串联. 串联的各部分可以改变顺序,并联的各部分可以改变顺序,都看作一种串并联网络. 输入n,输出有多少个n条边的串并联网络.$1\l

UVa10253

10253 Series-Parallel NetworksIn this problem you are expected to count two-terminal series-parallel networks. These are electricnetworks considered topologically or geometrically, that is, without the electrical properties of theelements connected.

series和 paralle

series 串行执行任务 特性:等待慢的一起输出 const { series } = require('gulp'); function javascript(cb) { // body omitted cb(); } function css(cb) { // body omitted cb(); } exports.build = series(javascript, css); paralle 并行执行任务 const { parallel } = require('gulp'); f

dp题目列表

10271 - Chopsticks 10739 - String to Palindrome 10453 - Make Palindrome 10401 - Injured Queen Problem 825 - Walking on the Safe Side 10617 - Again Palindrome 10201 - Adventures in Moving - Part IV 11258 - String Partition 10564 - Paths through the Ho

Enhancing network controls in mandatory access control computing environments

A?Mandatory?Access?Control?(MAC) aware firewall includes an extended rule set for MAC attributes, such as a security label or path. Application labels may be used to identify processes and perform firewall rule-checking. The firewall rule set may inc

JavaScript学习--Item27 异步编程异常解决方案

1.JavaScript异步编程的两个核心难点 异步I/O.事件驱动使得单线程的JavaScript得以在不阻塞UI的情况下执行网络.文件访问功能,且使之在后端实现了较高的性能.然而异步风格也引来了一些麻烦,其中比较核心的问题是: 1.函数嵌套过深 JavaScript的异步调用基于回调函数,当多个异步事务多级依赖时,回调函数会形成多级的嵌套,代码变成 金字塔型结构.这不仅使得代码变难看难懂,更使得调试.重构的过程充满风险. 2.异常处理 回调嵌套不仅仅是使代码变得杂乱,也使得错误处理更复杂.这