• 【Codeforces】 CF1830D Mex Tree


    题目链接

    CF方向
    Luogu方向

    题目解法

    路径上全 0 0 0 会使答案 − 1 -1 1,全 1 1 1 会使答案 − 2 -2 2
    考虑估算答案的下界,一个优秀的方案是黑白染色
    那么这时可以得到答案的下界为 n ( n + 1 ) − 2 n n(n+1)-2n n(n+1)2n

    然后我们就可以考虑暴力的 d p dp dp
    f i , j , 0 / 1 f_{i,j,0/1} fi,j,0/1 为在 i i i 的子树中, i i i 所在连通块大小为 j j j,颜色为 0 / 1 0/1 0/1 的方案数
    考虑 j j j 的取值范围,因为我们得到了答案的下界,所以可知 j ≤ n j\le \sqrt n jn
    直接树形 d p dp dp 即可
    时间复杂度 O ( T n n ) O(Tn\sqrt n) O(Tnn ),需要用 v e c t o r vector vector 存数组,且及时释放

    #include 
    #define pb push_back
    #define int long long
    using namespace std;
    const int N=200100,inf=1e18;
    int n,B,siz[N];
    int e[N<<1],ne[N<<1],h[N],idx;
    vector<int> f[N][2];
    inline int read(){
        int FF=0,RR=1;
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
        for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
        return FF*RR;
    }
    inline void chkmin(int &x,int y){ if(y<x) x=y;}
    void dfs(int u,int fa){
        f[u][0].pb(inf),f[u][0].pb(1),f[u][1].pb(inf),f[u][1].pb(2);
        siz[u]=1;
        for(int i=h[u];~i;i=ne[i]){
            int v=e[i];if(v==fa) continue;
            dfs(v,u);
            int LIM=min(siz[u]+siz[v],B)+5;
            vector<int> t[2];t[0].resize(LIM,inf),t[1].resize(LIM,inf);
            for(int j=1;j<=min(siz[u],B);j++) for(int k=1;k<=min(siz[v],B);k++){
                chkmin(t[0][j],f[u][0][j]+f[v][1][k]);
                chkmin(t[1][j],f[u][1][j]+f[v][0][k]);
                if(j+k<=B){
                    chkmin(t[0][j+k],f[u][0][j]+f[v][0][k]+j*k);
                    chkmin(t[1][j+k],f[u][1][j]+f[v][1][k]+j*k*2);
                }
            }
            siz[u]+=siz[v];
            f[u][0].resize(LIM);f[u][1].resize(LIM);
            for(int j=0;j<LIM;j++) f[u][0][j]=t[0][j],f[u][1][j]=t[1][j];
            t[0].clear(),t[0].shrink_to_fit();
            t[1].clear(),t[1].shrink_to_fit();
            f[v][0].clear(),f[v][0].shrink_to_fit();
            f[v][1].clear(),f[v][1].shrink_to_fit();
        }
    }
    void add(int x,int y){ e[idx]=y,ne[idx]=h[x],h[x]=idx++;}
    void work(){
        int n=read();
        for(int i=1;i<=n;i++) h[i]=-1;idx=0;
        for(int i=1;i<n;i++){
            int x=read(),y=read();
            add(x,y),add(y,x);
        }
        B=sqrt(n)+5;
        dfs(1,-1);
        int res=inf;
        for(int i=1;i<=min(siz[1],B);i++) res=min(res,min(f[1][0][i],f[1][1][i]));
        f[1][0].clear(),f[1][0].shrink_to_fit();
        f[1][1].clear(),f[1][1].shrink_to_fit();
        printf("%lld\n",n*(n+1)-res);
    }
    signed main(){
        int T=read();
        while(T--) work();
        fprintf(stderr,"%d ms\n",int64_t(1e3*clock()/CLOCKS_PER_SEC));
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
  • 相关阅读:
    uniapp小程序更新逻辑,按实际开发为主
    note_前端框架Vue的安装和简单入门(Windows 11)
    Pytorch框架学习记录6——torch.nn.Module和torch.nn.functional.conv2d的使用
    爬虫基本原理
    mapreduce的流程
    SD、SDIO和MMC接口基础和规范介绍
    计算机网络 第三章数据链路层
    Docker安装EMQX
    电子器件系列57:肖特基二极管(BAS7005)
    【JAVA学习笔记】39 - final关键字
  • 原文地址:https://blog.csdn.net/djx2021/article/details/133897613