zoukankan      html  css  js  c++  java
  • BZOJ4033: [HAOI2015]T1

    Description

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

    Input

     第一行包含两个整数 N, K 。

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

    Output

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

    Sample Input

    3 1
    1 2 1
    1 3 2

    Sample Output

    3

    HINT

    对于 100% 的数据, 0<=K<=N <=2000
     
     
    这是一道好题。。。
    设f[i][j]表示以i为根的子树选出j个黑点的最大收益,要费用提前计算。
    则考虑u的子节点v,在v的子树选k个,则f[u][j+k]=max(f[u][j]+f[v][k])+v子树中的黑点到外面的黑点距离+v子树中的白点到外面的白点距离
    后面的两个倒腾倒腾式子就行了。
    然后注意这样的代码是O(n^2)的而不是O(n^3)的。
    siz[x]=1;
    ren if(to[i]!=fa) {
        dp(to[i],x);
        rep(j,0,siz[x]) rep(k,0,siz[to[i]]) 
            update(f[x][j],f[to[i]][k]);
        siz[x]+=siz[to[i]];
    }
    View Code

    为什么呢?考虑那个二重循环,可以看做分别枚举两棵子树的每个点。你会发现,点对(u,v),只会在计算lca(u,v)的dp时才被考虑到,所以复杂度是O(n^2)。

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    typedef long long ll;
    const ll inf=1ll<<60;
    const int maxn=2010;
    int n,m,first[maxn],next[maxn<<1],to[maxn<<1],dis[maxn<<1],e;
    void AddEdge(int w,int v,int u) {
        to[++e]=v;dis[e]=w;next[e]=first[u];first[u]=e;
        to[++e]=u;dis[e]=w;next[e]=first[v];first[v]=e;
    }
    ll f[maxn][maxn],tmp[maxn],siz[maxn];
    void dp(int x,int fa) {
        siz[x]=1;
        ren if(to[i]!=fa) {
            dp(to[i],x);
            rep(j,0,siz[x]) rep(k,0,siz[to[i]]) 
                tmp[j+k]=max(tmp[j+k],f[x][j]+f[to[i]][k]+(ll)dis[i]*(k*(m-k)+(siz[to[i]]-k)*(n-m-siz[to[i]]+k)));
            siz[x]+=siz[to[i]];
            rep(j,0,siz[x]) f[x][j]=tmp[j],tmp[j]=-inf;
        }
    }
    int main() {
        n=read();m=read();
        rep(i,2,n) AddEdge(read(),read(),read());
        rep(i,1,n) rep(j,2,m) f[i][j]=-inf;
        rep(i,0,n) tmp[i]=-inf;
        dp(1,0);printf("%lld
    ",f[1][m]);
        return 0;
    }
    View Code
  • 相关阅读:
    Hadoop 学习笔记 (十) hadoop2.2.0 生产环境部署 HDFS HA Federation 含Yarn部署
    hadoop 2.x 安装包目录结构分析
    词聚类
    Hadoop 学习笔记 (十一) MapReduce 求平均成绩
    Hadoop 学习笔记 (十) MapReduce实现排序 全局变量
    Hadoop 学习笔记 (九) hadoop2.2.0 生产环境部署 HDFS HA部署方法
    Visual Studio Code 快捷键大全(Windows)
    Eclipse安装教程 ——史上最详细安装Java &Python教程说明
    jquery操作select(取值,设置选中)
    $.ajax 中的contentType
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5013536.html
Copyright © 2011-2022 走看看