题解:这里就体现并查集的好处了,买了A物品就要买B物品,同时买了B物品也要买A物品,所以存在一个捆绑关系,不如我们将这种有捆绑款系的物品加入到一个集合中,然后用背包算法解决
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int n,m,money,w[10005],v[10005],parent[10005],dp[100005];
//找祖宗
int find(int x){
if(parent[x]==x)return x;
return parent[x]=find(parent[x]);
}
int main(){
scanf("%d %d %d",&n,&m,&money);
//初始化集合
for(int i=1;i<=n;i++){
parent[i]=i;
}
//输入重量价值
for(int i=1;i<=n;i++){
cin>>w[i]>>v[i];
}
//建立集合关系
for(int i=0;i<m;i++){
int x,y;
cin>>x>>y;
parent[find(x)]=y;
}
//合并价值重量
for(int i=1;i<=n;i++){
if(parent[i]!=i){//买这件物品还需要买其他物品,就将所有物品价值重量整合到祖宗物品去
w[find(i)]+=w[i];
v[find(i)]+=v[i];
w[i]=0,v[i]=0; //重量价值捆绑到祖宗物品去了,自己要归零,防止重复购买
}
}
//背包算法
for(int i=1;i<=n;i++){
for(int j=money;j>=w[i];j--){
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
}
}
cout<<dp[money]<<endl;
system("pause");
return 0;
}