1455 搭配购买
现有的钱买到价值尽量多的云,这肯定是背包
买一朵云则和这朵云搭配的都要买,通过这句话,这肯定是一个有依赖性的背包
通过题意,一朵云只会被买一次,所以因该是一个01背包,因为有依赖性的背包很像一个树形结构,所以还得需要并查集转移方程,用并查集来判断每朵云最后是和怎么的一个配套,并且将同配套的云计算出主件附件价值和代价,最后使用01背包来决策即可
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
const int SIZE=10001;
int n,m,w;
int wi[SIZE],vi[SIZE];
int father[SIZE];
int f[SIZE];
inline int findd(int x)
{
return father[x]==x?x:findd(father[x]);
}
inline int read()
{
int s=0,f=1;
char c=getchar();
for(;c<'0'||c>'9';c=getchar())
{
if(c=='-')
f=-1;
}
for(;c>='0'&&c<='9';c=getchar())
{
s=s*10+c-48;
}
return s*f;
}
int main()
{
n=read();m=read();w=read();
for(int i=1;i<=n;i++)
{
father[i]=i;//集合初始化
}
for(int i=1;i<=n;i++)
{
vi[i]=read();
wi[i]=read();
}
int x,y;
for(int i=1;i<=m;i++)
{
x=read();
y=read();
father[findd(x)]=findd(y);//两个配套的云并查集
}
for(int i=1;i<=n;i++)
{
if(father[i]!=i)//配套
{
wi[findd(i)]+=wi[i];
wi[i]=0;//计算主件附件的代价
vi[findd(i)]+=vi[i];
vi[i]=0;
}
}
for(int i=1;i<=n;i++)
{
for(int j=w;j>=vi[i];j--)
{
f[j]=max(f[j],f[j-vi[i]]+wi[i]);
}
}
cout<<f[w]<<endl;
return 0;
}