您的位置:首页 > 其它

uva 10253 Series-Parallel Networks 树的性质,可重排列

2015-09-16 16:27 405 查看
题目:https://uva.onlinejudge.org/external/102/10253.pdf

对于一棵树,每个结点下的子树位置互换 ,还是同一棵树

可以利用这一性质解决 串并联问题,

如果是并联,那么把结点标为并联

,每个子树都是并联中的一条路线,(并联不考虑位置,正满足树的性质)

有的子树会是一个叶子结点,表示该路线上只有一条边

还有的子树,不止一条边,那么这条路线可以是串联(总的来说如此,不能是并联 ),(因为如果是并联本身就可以合并到父节点上)。

下面串联同方法,那么把结点标为串联,

每个结点表示串连中的一部分,(因为题目要求,串联互换位置属于用一种方法,所以树的结构满足这个条件)

int n;
ll dp[35];

int up[35];
int num[35];
ll dpans;

ll C(ll la,ll sm)  //一开始这里两个参数都是int ,没有考虑到传入的dp[]可以使long long
{
    ll ans=1;
    for(int i=1;i<=sm;i++)
    {
        ans=ans* ( la-i+1)/i;

    }
    return ans;
}
void dfs(int step,int ed,int sum)
{
    if(step==0)
    {
        int cnt=0;
        for(int i=1;i<n;i++)
        {
            cnt+=num[i];
        }
        if(sum!=n||cnt<=1 )  return;
        ll ans=1;
        for(int i=1;i<n;i++)
        {
            if(!num[i])  continue;
            ans*=  C(dp[i]+num[i]-1,num[i]     );

        }
        dpans+=ans;
        return;
    }
    if(sum>n)  return ;

    for(int i=up[step];i>=0;i--)
    {
        num[step]=i;
        dfs(step-1,ed,sum+ step*i);
    }
}

void DP(int x)  //搜索,把x 分成几类,比如 4=1+1+1+1 =1+1+2=2+2=1+3  !=4(因为不能分成只有1个叶子的子树)
{
     n=x;
    for(int i=1;i<x;i++)   
    {
       up[i]=x/i;    
    }
    dpans=0;   
    dfs(n-1,x,0);
    dp[x]=dpans;

}

int main()
{
    dp[1]=1;  //样例里dp[1]规定为1
    for(int i=2;i<=30;i++)
    {
        DP(i);             //一开始的dp[x] 意义是 有x个叶子(也就是x条边)的一个子树的方法数。
    }

    for(int i=2;i<=30;i++)
        dp[i]*=2;             //把并联节点换成串联,串联换成并联。   
    while(~scanf("%d",&n)&&n)
    {
        printf("%lld\n",dp
);
    }

    return 0;
}


#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<climits>
#include<queue>
#include<vector>
#include<map>
#include<sstream>
#include<set>
#include<stack>
#include<utility>
#pragma comment(linker, "/STACK:102400000,102400000")
#define PI 3.1415926535897932384626
#define eps 1e-10
#define sqr(x) ((x)*(x))
#define FOR0(i,n)  for(int i=0 ;i<(n) ;i++)
#define FOR1(i,n)  for(int i=1 ;i<=(n) ;i++)
#define FORD(i,n)  for(int i=(n) ;i>=0 ;i--)
#define  lson   num<<1,le,mid
#define rson    num<<1|1,mid+1,ri
#define MID   int mid=(le+ri)>>1
#define zero(x)((x>0? x:-x)<1e-15)
#define mk    make_pair
#define _f     first
#define _s     second

using namespace std;
//const int INF=    ;
typedef long long ll;
//const ll inf =1000000000000000;//1e15;
//ifstream fin("input.txt");
//ofstream fout("output.txt");
//fin.close();
//fout.close();
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
const int INF =0x3f3f3f3f;
//const int maxn=    ;
//const int maxm=    ;
//by yskysker123
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: