CF23 E. Tree 树形dp+高精度

题目链接

CF23 E. Tree

题解

CF竟让卡常QAQ
dp+高精度
dp[x][j]表示以x为根的子树,x所属的联通块大小为j,的最大乘积(不带j这块
最后f[x]维护以x为根的子树的最大答案
有点卡内存...高精压了4位
看了题解,了解到,其实这个dp的复杂度其实是O(n^2)
每次转移是复杂度是x之前的子树的sz * 当前子树的sz
相当于之前子树所有点和当前子树的点组成的点对数
而每个点对只会在lca处被计算一次
所以复杂度O(n^2)

代码

#include<cstdio> 
#include<cstring> 
#include<algorithm> 
inline int read() { 
    int x = 0,f = 1; 
    char c = getchar(); 
    while(c < '0' ||c > '9')c = getchar(); 
    while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar(); 
    return x * f; 
} 


const int L = 10000; 
const int maxn = 701; 
const int maxlen = 61; 
struct Bignum{ 
    int num[maxlen]; 
    int len; 
    Bignum () {memset(num,0,sizeof num); len = 0; }  
    void print() {
        for(int i = len;i;-- i) 
            if(i != len) { 
                if(num[i - 1] < L / 10) { 
                    printf("0"); 
                    if(num[i - 1] < L / 100) {
                        printf("0"); 
                        if(num[i - 1] < L / 1000) printf("0"); 
                    } 
                } 
                printf("%d",num[i - 1]); 
            } else printf("%d",num[i - 1]);  
        puts(""); 
    } 
} dp[maxn][maxn],Max[maxn]; 

Bignum operator * (Bignum a,Bignum b) { 
    int len = 0; 
    Bignum ret; 
    for(int i = 0;i < a.len;i ++) for(int j = 0;j < b.len;j ++) { 
        ret.num[i + j] += a.num[i] * b.num[j]; 
        if(ret.num[i + j] >= L) {  
            ret.num[i + j + 1] += ret.num[i + j] / L; 
            ret.num[i + j] %= L;    
        } 
    }  
    len = a.len + b.len; 
    while(ret.num[len-1] == 0 && len > 1) len --; 
    ret.len = len; 
    return ret; 
} 
Bignum operator / (Bignum a,int b) { 
    int len = a.len; 
    Bignum ret; 
    if(!b) return ret; 
    for(int i = 0;i < len;i ++) { 
        ret.num[i] += a.num[i]* b;  
        if(ret.num[i] >= L)  { 
            ret.num[i+1] += ret.num[i] / L; 
            ret.num[i] %= L; 
        } 
    } 
    while(ret.num[len] > 0)  ret.num[len+1] = ret.num[len] / L, ret.num[len ++] %= L; 
    ret.len = len;
    return ret;
} 
Bignum max(Bignum a,Bignum b)  { 
    if(a.len < b.len) return b; 
    if(a.len > b.len) return a; 
    for(int i = a.len-1;i >= 0;i --) {  
        if(a.num[i] < b.num[i]) return b; 
        if(a.num[i] > b.num[i]) return a;  
    } 
    return b; 
} 

//------------------------------- 
struct node { 
    int v,next;
}  edge[maxn << 1]; 
int head[maxn],num = 0; 
inline void add_edge(int u,int v) { 
    edge[++ num].v = v;edge[num].next = head[u];head[u] = num; 
}  int n; 
int siz[maxn]; 
void dfs(int x,int fa) { 
    siz[x] = 1; 
    dp[x][1].len = 1; dp[x][1].num[0] = 1; 
    for(int i = head[x];i;i = edge[i].next) { 
        int v = edge[i].v; 
        if(v == fa) continue; 
        dfs(v,x); 
        siz[x] += siz[v]; 
    } 
    for(int i = head[x];i;i = edge[i].next) { 
        int v = edge[i].v; 
        if(v == fa) continue; 
        for(int i = siz[x];i;-- i) { 
            if(dp[x][i].len)  
                for(int j = 1;j <= siz[v];++ j) 
                    if(dp[v][j].len) dp[x][i + j] = max(dp[x][i + j],dp[x][i] * dp[v][j]); 
            dp[x][i] = dp[x][i] * Max[v]; 
        } 
    } 
    for(int i = siz[x];i ;-- i) Max[x] = max(Max[x],dp[x][i] / i); 
} 

int main() { 
    n = read(); 
    for(int i = 1,u,v;i < n;++ i) { 
        u = read();v = read(); 
        add_edge(u,v); add_edge(v,u); 
    }   
    dfs(1,0); 
    Max[1].print(); 

猜你喜欢

转载自www.cnblogs.com/sssy/p/9445707.html
今日推荐