• b_lg_搭配购买(并查集+01背包)


    有一些云朵商品,你需要如果商品有搭配关系,则你需要购买具有搭配关系的所有云朵;
    已知你的初始财富以及各物品的价钱与价值,求出最大价值

    思路
    这题一开始写的(O(n^2m))的暴力,得分为40pt

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e4+5, W=1e3+5;
    int n,m,cap, fa[N], sz[N], f[W];
    struct node {
        int cost, val;
    } A[N];
    int find(int u) {
        return fa[u]==u ? u : fa[u]=find(fa[u]);
    }
    void merge(int u, int v) {
        int fu=find(u), fv=find(v);
        if (sz[fu]>sz[fv]) {
            fa[fv]=fu;
            sz[fu]+=sz[fv];
        } else {
            fa[fu]=fv;
            sz[fv]+=sz[fu];
        }
    }
    bool isConn(int u, int v) {
        return find(u)==find(v);
    }
    int buy(int u, int& cap) {
        int tot_val=A[u].val;
        for (int i=1; i<=n; i++) if (i!=u && isConn(i,u)) {
            cap-=A[i].cost, tot_val+=A[i].val;
            if (cap<0)
                return -1;        
        }
        return tot_val;
    }
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin>>n>>m>>cap;
        for (int i=1; i<=n; i++) cin>>A[i].cost>>A[i].val, fa[i]=i, sz[i]=1;
        for (int i=0; i<m; i++) {
            int u,v; cin>>u>>v;
            merge(u,v); 
        }
        for (int i=1; i<=n; i++) 
        for (int j=cap; j>=A[i].cost; j--) {
            int t=j-A[i].cost, v=buy(i,t);
            if (v!=-1)
                f[j]=max(f[j], f[t]+v);
        }
        cout<<f[cap];
        return 0;
    }
    

    直接用一个连通块的根记录总的cost、val,让子节点的cost、val变为0,这样就省去了buy函数的O(n)的检查时间

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e4+5, W=1e3+5;
    int n,m,cap, fa[N], sz[N], f[W];
    struct node {
        int cost, val;
    } A[N], B[N];
    int find(int u) {
        return fa[u]==u ? u : fa[u]=find(fa[u]);
    }
    void merge(int u, int v) {
        int fu=find(u), fv=find(v);
        if (sz[fu]>sz[fv]) {
            fa[fv]=fu;
            sz[fu]+=sz[fv];
        } else {
            fa[fu]=fv;
            sz[fv]+=sz[fu];
        }
    }
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin>>n>>m>>cap;
        for (int i=1; i<=n; i++) cin>>A[i].cost>>A[i].val, fa[i]=i, sz[i]=1;
        for (int i=0; i<m; i++) {
            int u,v; cin>>u>>v;
            merge(u,v);
        }
        for (int i=1; i<=n; i++) {
            int fi=find(i);
            B[fi].val+=A[i].val, B[fi].cost+=A[i].cost;
            A[i].val=0, A[i].cost=0;
        }
        for (int i=1; i<=n; i++)
        for (int j=cap; j>=B[i].cost; j--) {
            f[j]=max(f[j], f[j-B[i].cost]+B[i].val);
        }
        cout<<f[cap];
        return 0;
    }
    
  • 相关阅读:
    本地计算机上的SQL Server(MSSQLSERVER)服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止
    三色需求与工作层次
    dataGridView1.Rows[i].DefaultCellStyle.BackColor = Color.Gold;第一次无效
    c# 在DataTable的第一列(指定列)的前面添加一列
    去掉DataGridView最后一行的空白行,删除空白行
    阿里云OSS Multipart Upload上传实例
    sql 自动增加排序 并且初始值是000001
    HTML禁用Flash文件右键
    HTML,JS禁止鼠标右键、禁止全选、复制、粘贴的方法
    C#PDF转Word
  • 原文地址:https://www.cnblogs.com/wdt1/p/13784802.html
Copyright © 2020-2023  润新知