题意
有n个女孩,每个女孩有一个体重和颜值,并分为k个朋友团队。
两个女孩x,y在同一个团队的条件是存在a1(x), a2, ..., ak(y) 其中ai 和 ai + 1 是朋友( 1 ≤ i < k).
每个团队要么全取,那么取不超过。问在总重量不超过w的情况下能取到的最大颜值和。
思路
并查集+背包
代码
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
int n,m,weight;
int no[1010];
vector <int>f[1010];
int w[1010],b[1010],pre[1010];
long long maxnw[1010],maxb[1010];
long long d[1010];
int find_ds(int a){
return a== pre[a]?a:pre[a] = find_ds(pre[a]);
}
void combine(int a,int b){
int fa = find_ds(a),fb = find_ds(b);
if(fa != fb) pre[fa] = fb;
}
int main(){
int u,v;
scanf("%d%d%d",&n,&m,&weight);
for(int i = 1;i <= n;i ++) {
scanf("%d",&w[i]);
pre[i] = i;
}
for(int i= 1;i <= n;i ++) scanf("%d",&b[i]);
for(int i = 1;i <= m;i ++){
scanf("%d%d",&u,&v);
combine(u,v);
}
int maxn = 0;
for(int i = 1;i <= n;i ++){
int tmp = find_ds(i);
if(!no[tmp]) no[tmp] = ++maxn;
f[no[tmp]].push_back(i);
maxnw[no[tmp]] += w[i];
maxb[no[tmp]] += b[i];
}
for(int k = 0;k < f[1].size();k ++){
int nowno = f[1][k];
if(w[nowno] <= weight) d[w[nowno]] = max(d[w[nowno]],(long long)b[nowno]);
}
if(maxnw[1] <= weight) d[maxnw[1]] = max(d[maxnw[1]],maxb[1]);
for(int i = 1;i < maxn;i ++){
for(int j = weight;j >= 0;j --){
for(int k = 0;k < f[i + 1].size();k++){
int nowno = f[i + 1][k];
if(w[nowno] + j <= weight) d[j + w[nowno]] = max(d[j + w[nowno]],d[j] + b[nowno]);
}
if(maxnw[i + 1] + j <= weight) d[j + maxnw[i + 1]] = max(d[j + maxnw[i + 1]],d[j] + maxb[i+1]);
}
}
long long ans = 0;
for(int i = 0;i <= weight;i++) ans = max(ans,d[i]);
printf("%I64d\n",ans );
return 0;
}