【01背包 合并费用】搭配购买

传送门

题意

给定(n)朵云,编号(1,2dots ,n),每个云朵有一个价格(c_{i}),价值(d_{i})
一共有(w)的钱,一共(m)对关系((u_{i},v_{i}))表示((u_{i},v_{i}))需要一起购买,求最大价值

数据范围

(egin{array}{l}1 leq n leq 10000 \ 0 leq m leq 5000 \ 1 leq w leq 10000 \ 1 leq c_{i} leq 5000 \ 1 leq d_{i} leq 100 \ 1 leq u_{i}, v_{i} leq nend{array})

题解

将所有需要合并的价值和价格都合并到一个集合中,最后对所有不同集合做(01)背包即可

Code

#include<bits/stdc++.h>
using namespace std;

const int N=1e4+10;

int n,m,w;
int fa[N],c[N],d[N],dp[N];

int find(int x){
    if(fa[x]!=x) fa[x]=find(fa[x]);
    return fa[x];
}
void merge(int a,int b){
    int pa=find(a),pb=find(b);
    if(pa!=pb) {
        c[pb] += c[pa];
        d[pb] += d[pa];
        fa[pa] = pb;
    }
}
int main(){
    scanf("%d%d%d",&n,&m,&w);
    for(int i=1;i<=n;i++) fa[i] = i;
    for(int i=1;i<=n;i++) scanf("%d%d",&c[i],&d[i]);
    while(m--){
        int u,v; scanf("%d%d",&u,&v);
        merge(u,v);
    }
    for(int i=1;i<=n;i++){
        if(fa[i] == i)
            for(int j=w;j>=c[i];j--){
                dp[j]=max(dp[j],dp[j-c[i]]+d[i]);
            }
    }
    printf("%d
",dp[w]);
}
原文地址:https://www.cnblogs.com/hhyx/p/13426523.html