• Codeforces 23E Tree


    http://codeforces.com/problemset/problem/23/E

    题意:给一个树,求砍断某些边,使得所有联通块大小的乘积最大。
    思路:f[i][j]代表当前把j个贡献给i的父亲(也就是不计入f[i][j])的最大乘积是多少,转移就是背包转移

    记得最后统计答案的时候是f[i][j]*j

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #define wk sb
    #define ll long long
    int tot,son[200005],first[200005],next[200005],go[200005];
    int n;
    struct node{
        int a[35],n;
    }f[705][705];
    int read(){
        int t=0,f=1;char ch=getchar();
        while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
        while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
        return t*f;
    }
    void insert(int x,int y){
        tot++;
        go[tot]=y;
        next[tot]=first[x];
        first[x]=tot;
    }
    void add(int x,int y){
        insert(x,y);insert(y,x);
    }
    node operator *(node a,node b){
        node c;c.n=0;for (int i=0;i<=30;i++) c.a[i]=0;
        c.n=a.n+b.n;
        for (int i=1;i<=a.n;i++)
            for (int j=1;j<=b.n;j++){
                c.a[i+j-1]+=a.a[i]*b.a[j];
                c.a[i+j]+=c.a[i+j-1]/10000;
                c.a[i+j-1]%=10000;
            }
        int j=1;
        while (j<=c.n||c.a[j]>9999){
             c.a[j+1]+=c.a[j]/10000;
             c.a[j]%=10000;
             j++;
        }    
        while (j>1&&c.a[j]==0) j--;
        c.n=j;
        return c;
    }    
    node make(int x){
        node c;
        c.n=0;for (int i=0;i<=30;i++) c.a[i]=0;
        while (x){
           c.a[++c.n]=x%10000;
           x/=10000;
        }
        return c;
    }
    node up(node a,node b){
        if (a.n>b.n) return a;
        if (b.n>a.n) return b;
        for (int i=a.n;i>=1;i--)
            if (a.a[i]>b.a[i]) return a;
            else
            if (b.a[i]>a.a[i]) return b;
        return a;
    }
    void dfs(int x,int fa){
        f[x][1]=make(1);
        son[x]=1;
        for (int i=first[x];i;i=next[i]){
             int pur=go[i];
             if (pur==fa) continue;
             dfs(pur,x);
             for (int j=son[x];j>=0;j--)
                for (int k=son[pur];k>=0;k--)
                    f[x][j+k]=up(f[x][j+k],f[x][j]*f[pur][k]);
             son[x]+=son[pur];
        }
        f[x][0]=make(0);
        for (int i=1;i<=son[x];i++)
            f[x][0]=up(f[x][0],f[x][i]*make(i));    
    }
    int main(){
        n=read();
        for (int i=1;i<n;i++){
             int x=read(),y=read();
             add(x,y);
        }
        dfs(1,0);
        printf("%d",(int)f[1][0].a[f[1][0].n]);
        for (int i=f[1][0].n-1;i>=1;i--)
            printf("%.4d",(int)f[1][0].a[i]);
    }
  • 相关阅读:
    常用命令
    linux是文件里的内容整齐
    centos 7新机使用前操作
    Symmetric Tree @leetcode
    Binary Tree Inorder Traversal @leetcode
    [转]快速排序
    Remove Duplicates from Sorted Array @leetcode
    Remove Element @leetcode
    随笔1
    Unique Binary Search Trees @leetcode
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5675776.html
Copyright © 2020-2023  润新知