传送门
题意
给定(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]);
}