分析:可以看成是特殊的有依赖的背包问题,因为有依赖的背包对于子树是可选可不选,这里是必选全部选,反而变得更加简单了
所以我们可以把一堆搭配看成一个集合,然后运用并查集维护并查集的拓展域,做01背包问题
并查集拓展域
- 价格域 v ==集合中所有价值和
- 价值域 w ==集合中所有价格和
#include <iostream>
#include <algorithm>
using namespace std;
const int N=10010;
int v[N]; //云的集合,价格
int w[N]; //价值
int p[N];
int dp[N];
int find(int x)
{
if(x!=p[x])
p[x]=find(p[x]);
return p[x];
}
int main()
{
int n,m,W;
cin>>n>>m>>W;
for(int i=1;i<=n;i++)
cin>>v[i]>>w[i],p[i]=i;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
x=find(x),y=find(y);
if(x==y) continue; //为了避免重复加减
//维护拓展域
v[x]+=v[y];w[x]+=w[y];
p[y]=x;
}
for(int i=1;i<=n;i++)
if(p[i]==i)
{
for(int j=W;j>=v[i];j--)
dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
}
cout<<dp[W];
return 0;
}