bzoj1945: [Ceoi2007]Royaltreasury

传送门
裸的树形dp。
f[i][0/1]表示当前位置没用/用了
转移暴力就可以了
然后就是喜闻乐见的高精度模板了。

#include<cmath>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 1005
#define ll long long
#define mo 1000000000
using namespace std;
struct bignum{
    ll a[25];
    bignum(int x=0){
        memset(a,0,sizeof(a));
        if (!x) return;
        a[1]=x; a[0]=1;
    }
    friend bignum operator +(bignum a,bignum b){
        bignum c;
        c.a[0]=max(a.a[0],b.a[0]);
        for (int i=1;i<=c.a[0];i++) c.a[i]=a.a[i]+b.a[i];
        for (int i=1;i<=c.a[0];i++){
            c.a[i+1]+=c.a[i]/mo;
            c.a[i]%=mo;
        }
        if (c.a[c.a[0]+1]) c.a[0]++;
        return c;
    }
    friend bignum operator *(bignum a,bignum b){
        bignum c;
        for (int i=1;i<=a.a[0];i++){
            ll x=0;
            for (int j=1;j<=b.a[0];j++){
                x+=c.a[i+j-1]+a.a[i]*b.a[j];
                c.a[i+j-1]=x%mo;
                x/=mo;
            }
            c.a[i+b.a[0]]=x;
        }
        c.a[0]=a.a[0]+b.a[0];
        while (c.a[0]&&!c.a[c.a[0]]) c.a[0]--;
        return c;
    }
    void print(){
        printf("%lld",a[a[0]]);
        for (int i=a[0]-1;i>0;i--)
            printf("%09lld",a[i]);
        puts("");
    }
};
vector<int> e[N];
int f[N][2];
bignum g[N][2];
int n,x,y,z;
void dfs(int x,int y){
    if (f[x][y]!=-1) return;
    f[x][y]=0; g[x][y]=bignum(0);
    if (!e[x].size()&&y) return;
    if (!y){
        g[x][y]=bignum(1);
        for (int i=0;i<e[x].size();i++){
            dfs(e[x][i],0); dfs(e[x][i],1);
            if (f[e[x][i]][0]>f[e[x][i]][1]){
                f[x][y]=f[x][y]+f[e[x][i]][0];
                g[x][y]=g[x][y]*g[e[x][i]][0];
            }
            else{
                f[x][y]=f[x][y]+f[e[x][i]][1];
                if (f[e[x][i]][0]!=f[e[x][i]][1])
                    g[x][y]=g[x][y]*g[e[x][i]][1];
                else g[x][y]=g[x][y]*(g[e[x][i]][0]+g[e[x][i]][1]);
            }
        }
        return;
    }
    int p; bignum q;
    for (int i=0;i<e[x].size();i++)
        dfs(e[x][i],0),dfs(e[x][i],1);
    for (int i=0;i<e[x].size();i++){
        p=0; q=bignum(1);
        for (int j=0;j<e[x].size();j++)
            if (j!=i){
                if (f[e[x][j]][0]>f[e[x][j]][1]){
                    p=p+f[e[x][j]][0];
                    q=q*g[e[x][j]][0];
                }
                else{
                    p=p+f[e[x][j]][1];
                    if (f[e[x][j]][0]!=f[e[x][j]][1])
                        q=q*g[e[x][j]][1];
                    else q=q*(g[e[x][j]][0]+g[e[x][j]][1]);
                }
            }
            else{
                p=p+f[e[x][j]][0]+1;
                q=q*g[e[x][j]][0];
            }
        if (p>f[x][y]){
            f[x][y]=p; g[x][y]=bignum(0);
        }
        if (p==f[x][y])
            g[x][y]=g[x][y]+q;
    }
}
int main(){
    scanf("%d",&n);
    for (int i=1;i<=n;i++){
        scanf("%d%d",&x,&y);
        while (y--){
            scanf("%d",&z);
            e[x].push_back(z);
        }
    }
    memset(f,-1,sizeof(f));
    dfs(1,0);
    dfs(1,1);
    if (f[1][0]<f[1][1])
        f[1][0]=f[1][1],g[1][0]=0;
    if (f[1][0]==f[1][1])
        g[1][0]=g[1][0]+g[1][1];
    printf("%d\n",f[1][0]);
    g[1][0].print();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值