题目链接:
div.1 741B
大意:
有一群人,已知每个人的朋友、及她的体重、颜值,对于每个朋友集合,要么只取一个,要么全部取,要么不取,对于限制条件 W,求最大的价值。
思路:
并查集+分组背包。
(温习并规范了下并查集的写法)
#include<bits/stdc++.h>
using namespace std;
#define D(v) cout<<#v<<" "<<v<<endl
#define mem(s,t) memset(s,t,sizeof(s))
const int MAXN=1010;
int n,m,W;
int w[MAXN],b[MAXN];
int F[MAXN];
int dp[MAXN];
vector<int> group[MAXN];
int findf(int x){return F[x]==x?x:findf(F[x]);}
void megre(int x,int y){
int fx=findf(x);
int fy=findf(y);
if(fx!=fy){
F[fx]=fy;
}
}
int main(){
while(~scanf("%d%d%d",&n,&m,&W)){
mem(dp,0);
for(int i=1;i<=n;i++){
scanf("%d",&w[i]);
}
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
}
for(int i=0;i<=n;i++) F[i]=i;
for(int i=0;i<m;i++){
int x,y;
scanf("%d%d",&x,&y);
megre(x,y);
}
for(int i=1;i<=n;i++){
group[findf(i)].push_back(i);
}
for(int i=1;i<=n;i++){
if(findf(i)!=i) continue;
for(int k=W;k>=0;k--){
int sumw=0,sumb=0;
for(int j=0;j<group[i].size();j++){
sumw+=w[group[i][j]];
sumb+=b[group[i][j]];
if(k>=w[group[i][j]]){
dp[k]=max(dp[k],dp[k-w[group[i][j]]]+b[group[i][j]]);
}
}
if(k>=sumw){
dp[k]=max(dp[k],dp[k-sumw]+sumb);
}
}
}
printf("%d\n",dp[W]);
}
return 0;
}
参考博客:http://blog.csdn.net/zwj1452267376/article/details/53511600