【Luogu】P1411树(树形高精DP)

  题目链接

  我貌似又做了一道高精题呢(笑)

  这题的DP方程很好想,设f[i][j]表示i为根的子树,i所在联通块大小为j的最大值,然后乱搞

  但是要高精,那么搞是得要高精除的

  所以考虑f[i][j]是除以j后的最大值,就可以只写高精乘了

  不过卡常,下面代码只能得95分

// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define maxl 120
#define maxn 702
#define check(x) if(x==0)    x=++tot;
using namespace std;

inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

struct BigInteger{
    int s[maxl],len;
    BigInteger(){len=0;memset(s,0,sizeof(s));}
    BigInteger operator =(const char *c){
        len=0;
        for(int i=strlen(c+1);i;--i)    s[++len]=c[i]-'0';
        return *this;
    }
    BigInteger operator =(const int num){
        char c[maxl];
        sprintf(c+1,"%d",num);
        (*this)=c;
        return *this;
    }
    BigInteger operator *(BigInteger a){
        BigInteger ans;
        ans.len=len+a.len;
        for(int i=1;i<=len;++i)
            for(register int j=1;j<=a.len;++j)
                ans.s[i+j-1]+=s[i]*a.s[j];
        int g=0;
        for(int i=1;i<=(len+a.len)||g;++i){
            ans.s[i]+=g;
            g=ans.s[i]/10;
            ans.s[i]%=10;
            if(ans.len<i)    ans.len=i;
        }
        while(ans.len&&ans.s[ans.len]==0)    ans.len--;
        return ans;
    }
    BigInteger operator *(const int a){
        BigInteger ans=(*this);
        int g=0,lim=ans.len;
        for(int i=1;(i<=lim)||g;++i){
            ans.s[i]=ans.s[i]*a+g;
            g=ans.s[i]/10;
            ans.s[i]%=10;
            if(i>ans.len)    ans.len=i;
        }
        while(ans.len&&ans.s[ans.len]==0)    ans.len--;
        return ans;
    }
    bool operator <(const BigInteger a)const{
        if(len!=a.len)    return len<a.len;
        for(int i=len;i;--i)
            if(s[i]!=a.s[i])    return s[i]<a.s[i];
        return 0;
    }
};

inline void print(BigInteger a){
    if(a.len==0)    putchar('0');
    for(int i=a.len;i;--i)    putchar(a.s[i]+'0');
}

BigInteger f[maxn*350];
int tot;
int size[maxn];
int pos[maxn][maxn];
BigInteger ans;

struct Edge{
    int next,to;
}edge[maxn*3];
int head[maxn],num;
inline void add(int from,int to){
    edge[++num]=(Edge){head[from],to};
    head[from]=num;
}

void dfs(int x,int fa){
    check(pos[x][0]);    check(pos[x][1]);
    f[pos[x][0]]=1;f[pos[x][1]]=1;    size[x]=1;
    for(int i=head[x];i;i=edge[i].next){
        int to=edge[i].to;
        if(to==fa)    continue;
        dfs(to,x);
        size[x]+=size[to];
        for(int j=size[x];j>=0;--j){
            check(pos[x][j]);
            for(int k=min(j,size[x]-size[to]);k>=min(1,size[x]-size[to]);--k)
                if(f[pos[x][j]]<f[pos[to][j-k]]*f[pos[x][k]]){
                    f[pos[x][j]]=f[pos[to][j-k]]*f[pos[x][k]];
                }
        }
    }
    for(int j=1;j<=size[x];++j){
        if(f[pos[x][0]]<f[pos[x][j]]*j){
            f[pos[x][0]]=f[pos[x][j]]*j;
            if(ans<f[pos[x][0]])    ans=f[pos[x][0]];
        }
    }
}


int main(){
    int n=read();
    for(int i=1;i<n;++i){
        int x=read(),y=read();
        add(x,y);
        add(y,x);
    }
    dfs(1,1);
    print(ans);
}

 

posted @ 2018-01-28 20:42  Konoset  阅读(360)  评论(0编辑  收藏  举报