zoukankan      html  css  js  c++  java
  • [Codeforces 23E] Tree

    Brief Intro:

    一棵树,删去若干条边,最大化得到的所有连通块大小的乘积

    Algorithm:

    这其实算是一类题型吧,虽然这是我做的第一题

    树形DP,维护关于子树根节点的信息

    此处用dp[i][s],表示以i为根的子树,且i所属连通块的大小为s时的最大值

    转移时还是树形DP的常规套路,用类似背包的形式转移:dp[i的孩子][k]*dp[i][s]  ------->   dp[i][k+s]

    需要注意的是,此题需要高精度,写一个Big Integer模板类即可

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    
    template<class T> inline void putnum(T x)
    {
        if(x<0)putchar('-'),x=-x;
        register short a[20]={},sz=0;
        while(x)a[sz++]=x%10,x/=10;
        if(sz==0)putchar('0');
        for(int i=sz-1;i>=0;i--)putchar('0'+a[i]);
    }
    
    inline ll read()
    {
        char ch;ll num,f=0;
        while(!isdigit(ch=getchar())) f|=(ch=='-');
        num=ch-'0';
        while(isdigit(ch=getchar())) num=num*10+ch-'0';
        return f?-num:num;
    }
    
    const int MAXN=705;
    const int MAXLEN=120;
    
    struct BI  模板类
    {
        int d[MAXLEN],len;
        
        BI(){memset(d,0,sizeof(d)),len=1;}
        BI(int num){*this=num;}
        
        BI& operator = (const int& num)
        {
            memset(d,0,sizeof(d));
            int t=num;len=0;
            while(t) d[++len]=t%10,t/=10;
            return *this;
        }
        
        void clear()
        {
            while(len>1 && !d[len]) len--;
        }
        
        BI operator + (const BI& num)
        {
            BI ret=*this;
            ret.len=max(num.len,len);
            for(int i=1;i<=ret.len;i++)
            {
                ret.d[i]+=num.d[i];
                if(ret.d[i]>=10) ret.d[i]-=10,ret.d[i+1]++; 
            }
            if(ret.d[ret.len+1]) ret.len++;
            return ret;
        }
        
        BI operator * (const BI& num) const
        {
            BI ret;
            for(int i=1;i<=len;i++)
                for(int j=1;j<=num.len;j++)
                    ret.d[i+j-1]+=d[i]*num.d[j];
            for(int i=1;i<=len+num.len;i++)
                ret.d[i+1]+=ret.d[i]/10,ret.d[i]%=10;
            ret.len=len+num.len+1;
            ret.clear();
            return ret;
        }
        
        bool operator > (const BI& num)
        {
            if(num.len!=len) return len>num.len;
            for(int i=len;i>=1;i--)     //注意,比较是从后往前比
                if(d[i]!=num.d[i]) return d[i]>num.d[i];
            return false;
        }
        
        void print()
        {
            for(int i=len;i>=1;i--) putnum(d[i]);
        }
    }dp[MAXN][MAXN];
    
    int n,sz[MAXN];
    vector<int> G[MAXN];
    
    void dfs(int u,int anc)
    {
        sz[u]=1;dp[u][1]=1;
        for(int i=0;i<G[u].size();i++)
        {
            int v=G[u][i];
            if(v==anc) continue;
            dfs(v,u);
            
            for(int Nu=sz[u];Nu>=1;Nu--)
                for(int Nv=sz[v];Nv>=0;Nv--)
                {
                    BI t=dp[u][Nu]*dp[v][Nv];
                    if(t>dp[u][Nu+Nv]) dp[u][Nu+Nv]=t;
                }
            sz[u]+=sz[v];  //size在转移后再更新
        }
        
        for(int i=1;i<=sz[u];i++)
        {
            BI t=dp[u][i]*BI(i);
            if(t>dp[u][0]) dp[u][0]=t;  //用0号存储最值
        }
    }
    
    int main()
    {
        n=read();
        for(int i=1;i<n;i++)
        {
            int x=read(),y=read();
            G[x].push_back(y);G[y].push_back(x);
        }
        dfs(1,0);
        dp[1][0].print();
        return 0;
    }

    Review:

    1、对连续的乘法要敏感,查看是否需要高精度

    2、BI重载>号时,要从后往前判断

  • 相关阅读:
    layui弹出层:使用icon图标小结
    layui弹出层:使用icon图标小结
    存储过程分页
    .net 更改GridView标题文字
    PHP文件结尾符的问题
    JAVA中使用JSON进行数据传递
    Ubuntu LAMP环境安装
    PHP中使用class_exists判断类是否存在
    NS_ERROR_XPC_BAD_CONVERT_JS: Could not convert JavaScript argument
    Android开发教程 葵花宝典第六层 控件之 Dialog ListView GridView
  • 原文地址:https://www.cnblogs.com/newera/p/9080064.html
Copyright © 2011-2022 走看看