zoukankan      html  css  js  c++  java
  • [HAOI2015]树上染色

    Description:

    有一棵点数为 N 的树,树边有边权。给你一个在 0~ N 之内的正整数 K ,你要在这棵树中选择 K个点,将其染成黑色,并将其他 的N-K个点染成白色 。 将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间的距离的和的受益。问受益最大值是多少。

    Hint:

    (n le 2^3)

    Solution:

    很好的树型dp题

    设状态(f[i][j])表示i点子树染j个黑点的最大距离和

    然而无法转移

    换一种角度,考虑每条边对答案的贡献

    设一条边的下面一端u的子树中有k个黑点

    (Ans=k*(m-k)+(sz[u]-k)*(n-sz[u]-m+k))

    这样就能用树型背包做了

    #include <map>
    #include <set>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ls p<<1 
    #define rs p<<1|1
    using namespace std;
    typedef long long ll;
    const int mxn=1e5+5;
    int n,m,cnt,hd[mxn],sz[mxn];
    ll f[2005][2005];
    
    inline int read() {
        char c=getchar(); int x=0,f=1;
        while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
        while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
        return x*f;
    }
    inline void chkmax(int &x,int y) {if(x<y) x=y;}
    inline void chkmin(int &x,int y) {if(x>y) x=y;}
    
    struct ed {
        int to,nxt,w;
    }t[mxn<<1];
    
    inline void add(int u,int v,int w) {
        t[++cnt]=(ed) {v,hd[u],w}; hd[u]=cnt;
    }
    
    void dfs(int u,int fa) 
    {
        sz[u]=1; f[u][0]=f[u][1]=0;
        for(int i=hd[u];i;i=t[i].nxt) {
            int v=t[i].to;
            if(v==fa) continue ;
            dfs(v,u); sz[u]+=sz[v];
            for(int j=min(m,sz[u]);j>=0;--j) { 
                if(f[u][j]!=-1)
                f[u][j]+=f[v][0]+1ll*sz[v]*(n-m-sz[v])*t[i].w; //这里一定要先处理v为0的答案,如果在后面转移就会错
                for(int k=min(j,sz[v]);k;--k) {
                    if(f[u][j-k]==-1) continue ;
                    ll val=1ll*(k*(m-k)+(sz[v]-k)*(n-m-sz[v]+k))*t[i].w;
                    f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]+val);
                }
            }
        }
    }
    
    int main()
    {
        memset(f,-1,sizeof(f));
        n=read(); m=read(); int u,v,w;
        for(int i=1;i<n;++i) {
            u=read(); v=read(); w=read();
            add(u,v,w); add(v,u,w);
        }
        dfs(1,1);
        printf("%lld",f[1][m]);
        return 0;
    }
    
    
  • 相关阅读:
    图文详解k8s自动化持续集成之GitLab CI/CD
    GitLab CI/CD 进行持续集成
    高性能伪事务之Lua in Redis
    面向对象之组合VS继承:继承过时了?
    Go依赖模块版本之Module避坑使用详解
    Maven3路程(三)用Maven创建第一个web项目(1)
    C#通过WIN32 API实现嵌入程序窗体
    Selenium自動化測試(Python+VS2013)-基礎篇-環境安裝
    VS2013中Python学习笔记[环境搭建]
    win7 windows server 2008R2下 https SSL证书安装的搭配(搭配https ssl本地测试环境)
  • 原文地址:https://www.cnblogs.com/list1/p/10555360.html
Copyright © 2011-2022 走看看