题目:http://codeforces.com/problemset/problem/742/D
题意:若干人和关系,限定容量,每次能取一个联通块中的一个或全部,求取得的最大值。
思路:并查集处理玩关系后用背包即可。
分组背包:若干组,每组只能选0或1个
for i : [1..z] //组数
for j : [v..1] //容量
for k : [1..n] //组内
dp[j] = max(dp[j], dp[j-w[i][k]]+v[i][k]);
#include <bits/stdc++.h>
#define LL long long
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
const int maxn = 1e3+5;
int n, m, w, mp[maxn], a[maxn], b[maxn], fa[maxn], dp[maxn], suma[maxn], sumb[maxn];
int Find(int x){return x == fa[x] ? x : fa[x] = Find(fa[x]);}
vector <int> vec[maxn];
int main()
{
cin >> n >> m >> w;
for(int i=1; i<=n; i++) fa[i] = i;
for(int i=1; i<=n; i++) cin >> a[i];
for(int i=1; i<=n; i++) cin >> b[i];
int u, v;
for(int i=1; i<=m; i++){
cin >> u >> v;
int x = Find(u), y = Find(v);
if(x != y) fa[y] = x;
}
int cnt = 0;
for(int i=1; i<=n; i++){
int tmp = Find(i);
if(!mp[tmp]) mp[tmp] = ++cnt;
vec[mp[tmp]].push_back(i);
suma[mp[tmp]] += a[i], sumb[mp[tmp]] += b[i];
}
for(int i=1; i<=cnt; i++){
for(int j=w; j>=1; j--){
int sz = vec[i].size();
for(int k=0; k<sz; k++){
int v = vec[i][k];
if(a[v] <= j) dp[j] = max(dp[j], dp[j-a[v]] + b[v]);
}
if(suma[i] <= j) dp[j] = max(dp[j], dp[j-suma[i]]+sumb[i]);
}
}
cout << dp[w] << endl;
}