• BZOJ 4033: [HAOI2015]树上染色


    Time Limit: 10 Sec Memory Limit: 256 MB
    Submit: 2569 Solved: 1088
    [Submit][Status][Discuss]
    Description

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

    第一行两个整数N,K。
    接下来N-1行每行三个正整数fr,to,dis,表示该树中存在一条长度为dis的边(fr,to)。
    输入保证所有点之间是联通的。
    N<=2000,0<=K<=N
    Output

    输出一个正整数,表示收益的最大值。
    Sample Input

    5 2

    1 2 3

    1 5 1

    2 3 1

    2 4 2

    Sample Output

    17

    【样例解释】

    将点1,2染黑就能获得最大收益。

    题解

    dp[x][j]表示以x为根的子树选了j个黑点的贡献
    dp[x][j]=max(dp[x][j],dp[x][j-o]+dp[u][o]+val)
    此时的val应该等于一边的黑色*另一边的黑色*距离+一边的白色*另一边的白色*距离
    

    代码

    #include<bits/stdc++.h>
    #define LL long long
    
    using namespace std;
    const int MAXN = 2005;
    
    int k,n,head[MAXN],cnt,siz[MAXN];
    LL dp[MAXN][MAXN];     //dp[i][j]表示前i个点,染了j个黑色 
    
    struct Edge{
        int nxt,to,val;
    }edge[MAXN*2];
    
    int read() {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    
    
    inline void add(int bg,int ed,int w){
        edge[++cnt].to=ed;
        edge[cnt].val=w;
        edge[cnt].nxt=head[bg];
        head[bg]=cnt;
    }
    
    inline void dfs(int x,int fa){
        siz[x]=1;
        for(int i=1;i<=k;i++) dp[x][i]=-1;dp[x][0]=dp[x][1]=0;
        for(register int i=head[x];i;i=edge[i].nxt){
            int u=edge[i].to;
            if(u==fa) continue;
            dfs(u,x);
            siz[x]+=siz[u];
        }
        for(register int i=head[x];i;i=edge[i].nxt){
            int u=edge[i].to;
            if(u==fa) continue;
            int minn=min(k,siz[x]);
            for(register int j=minn;j>=0;j--){int mi=min(j,siz[u]);
                for(register int s=0;s<=mi;s++)if(~dp[x][j-s]){
                    LL v=(LL)s*(k-s)*edge[i].val+(LL)(siz[u]-s)*(n-k+s-siz[u])*edge[i].val;
                    dp[x][j]=max(dp[x][j],dp[x][j-s]+dp[u][s]+v);
                }
            }
        }
    }
    
    int main(){
        n=read();k=read();
        for(int i=1;i<n;i++){
            int x,y,z;
            x=read();y=read();z=read();
            add(x,y,z);add(y,x,z);
        }
        dfs(1,0);
        printf("%lld",dp[1][k]);
        return 0;
    }
  • 相关阅读:
    table变宽格式
    IE11兼容性设定
    Spring AOP注解失效的坑及JDK动态代理
    关于何时执行shiro AuthorizingRealm 里的 doGetAuthenticationInfo与doGetAuthorizationInfo
    后端接收json数据交互
    关于JavaDate数据返回到前端变数字的问题(并引申到前后端时间的传输)
    git 列出两个分支 或者两个提交版本之间不同的文件名字
    map put相同的key
    MyBatis 中如何调用 Java 的 enum (枚举) 字段
    @ResponseBody 和 @RequestBody 的作用
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9677052.html
Copyright © 2020-2023  润新知