zoukankan      html  css  js  c++  java
  • JSOI2016 最佳团体

    题目链接:戳我

    首先,你要知道这道题是一棵树!
    然后,就是从树上选择K个点,让他们的权值和最大,其中如果选择了一个点,那么它的父亲一定要选。
    有依赖的背包问题。
    (dp[i][j])表示在以i为根的子树中,选择j个点的最大权值。
    但是直接在树上做应该是(O(n^2k))的,所以我们考虑优化——
    就是我们考虑在树上将背包合并,这样子每个子树都只会被合并一次,这样时间复杂度就降为了(O(nk))
    然后就能过了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 3010
    #define eps 1e-6
    using namespace std;
    int n,m,t,tot;
    int head[MAXN],siz[MAXN],fa[MAXN];
    double dp[MAXN][MAXN],now[MAXN],tmp[MAXN],w[MAXN],v[MAXN];
    struct Edge{int nxt,to;}edge[MAXN<<1];
    inline void add(int from,int to){edge[++t].nxt=head[from],edge[t].to=to,head[from]=t;}
    inline void merge(int x,int y)
    {
        for(int i=0;i<=m+1;i++) tmp[i]=-1e9;
        for(int i=1;i<=siz[x];i++)
            for(int j=1;j<=siz[y];j++)
                tmp[i+j]=max(tmp[i+j],dp[x][i]+dp[y][j]);
        for(int i=0;i<=m+1;i++) dp[x][i]=max(dp[x][i],tmp[i]);
    }
    inline void solve(int x)
    {
        dp[x][1]=now[x];
        siz[x]=1;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            solve(v);
            merge(x,v);
            siz[x]+=siz[v];
        }
    }
    inline bool check(double x)
    {
        for(int i=0;i<=n;i++)
            for(int j=0;j<=m+1;j++)
                dp[i][j]=-1e9;
        memset(siz,0,sizeof(siz));
        for(int i=1;i<=n;i++) now[i]=v[i]-w[i]*x;
        solve(0);
        if(dp[0][m+1]>=0) return true;
        else return false;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin); 
        #endif
        scanf("%d%d",&m,&n);
        double l=1e9,r=-1e9;
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf%d",&w[i],&v[i],&fa[i]);
            add(fa[i],i);
            l=min(l,v[i]/w[i]);
            r=max(r,v[i]/w[i]);
        }
        
        while(l+eps<r)
        {
            double mid=(l+r)/2;
            if(check(mid)) l=mid;
            else r=mid;
        }
        printf("%.3lf
    ",l);
        return 0;
    }
    
    
  • 相关阅读:
    [HNOI2008] [BZOJ1008] 越狱|组合数学
    (转)位运算简介及使用技巧
    AW297 赤壁之战(数据结构优化DP)
    AW280 陪审团
    AW288 休息时间
    AW281 硬币
    AW383 观光
    AW366 看牛 (欧拉回路)
    AW365 圆桌骑士
    AW363 B城
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10909296.html
Copyright © 2011-2022 走看看