搭配购买
策略:01背包 + 并查集
本题是经典的最简单捆绑购买类型,即所有涉及到相同性质的物品都得捆绑购买
1.怎么判断是否存在捆绑关系
这就是经典的并查集模型该解决的问题了,即通过并查集的思想将所有相关联的物品连在一起,在连的过程中不断归并物品的价值和体积
2.如何求解
将所有的捆绑物品全部都归并之后,就变成了数量为1,体积为Σv[i],价值为Σw[i]的物品,即化简成了最基础的01背包问题。
解题代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 10010;
int n, m, k, cnt;
int v[N], w[N];
int f[N];
int d[N];
int find(int x)
{
if(x != f[x]) f[x] = find(f[x]);
return f[x];
}
int main()
{
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= n; i ++ )
{
scanf("%d%d", &v[i], &w[i]);
f[i] = i;
}
for(int i = 1; i <= m; i ++ )
{
int a, b;
scanf("%d%d", &a, &b);
//并查集 + 归并
a = find(a), b = find(b);
if(a != b)
{
f[b] = a;
v[a] += v[b];
w[a] += w[b];
}
}
//一维01背包
for(int i = 1; i <= n; i ++ )
{
if(f[i] == i)
for(int j = k; j >= v[i]; j --)
d[j] = max(d[j], d[j - v[i]] + w[i]);
}
printf("%d", d[k]);
return 0;
}