并查集–搭配购买
并查集(整体性态)+01背包
题目中有很重要的一个性质,表示买 ui 就必须买 vi,同理,如果买 vi 就必须买 ui。这表示具有双向的传递性,由此我们可以将满足双向传递性的云朵放在一个并查集中。
将一个集合视为一个整体,整体性态为这个整体的价值v和价钱u。简化为一堆物品价值为vi,价钱为ui,放入体积为jeo钱数的背包。标准的零一背包问题。
C++ 代码
#include<iostream>
using namespace std;
const int N=10010;
int n,m,w;
int f[N];
int c[N],d[N],p[N];
int find(int x)
{
if(x!=p[x]) p[x]= find(p[x]);
return p[x];
}
int main()
{
cin>>n>>m>>w;
for(int i=1;i<=n;i++) p[i]=i;
for(int i=1;i<=n;i++) cin>>c[i]>>d[i];
int res=0;
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
int pa=find(u),pb=find(v);
if(pa!=pb)
{
p[pa]=pb;
d[pb]+=d[pa];
c[pb]+=c[pa];//合并集合的过程中 维护整体性态
}
}
for(int i=1;i<=n;i++)
{
if(p[i]==i)//这是一个连通块 取一堆物品的代表元素,视为一个物品
{
for(int j=w;j>=c[i];j--)
f[j]=max(f[j],f[j-c[i]]+d[i]);
}
}
cout<<f[w];
return 0;
}