点击跳转了解题意
题解:起初看到这道题,我以为它是一道像金明的预算方案一样的树形背包dp,但仔细观察发现了它们的不同,这道题规定了买一件物品其它
有关系的物品必须都买,再仔细一想,有了这种关系,主件和附件不就成了同一件物品了嘛,所以我们用并查集维护一下关系,然后将有关系
的物品合并为一件物品再做01背包即可。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 10005 6 7 using namespace std; 8 9 int f[maxn],c[maxn],w[maxn]; 10 int n,vmax,m; 11 int dp[maxn]; 12 13 inline int find(int k) 14 { 15 if(f[k]==k) return f[k]; 16 return f[k]=find(f[k]); 17 } 18 19 int main() 20 { 21 scanf("%d%d%d",&n,&m,&vmax); 22 for(int i=1;i<=n;i++) 23 f[i]=i; 24 for(int i=1;i<=n;i++) 25 scanf("%d%d",&w[i],&c[i]); 26 for(int i=1;i<=m;i++) 27 { 28 int x,y; 29 scanf("%d%d",&x,&y);; 30 int f1=find(x); 31 int f2=find(y); 32 f[f1]=f2; 33 } 34 for(int i=1;i<=n;i++) 35 { 36 int f1=find(i); 37 if(f1!=i) 38 { 39 c[f1]+=c[i]; 40 w[f1]+=w[i]; 41 c[i]=w[i]=0; 42 } 43 } 44 for(int i=1;i<=n;i++) 45 for(int v=vmax;v>=w[i];v--) 46 dp[v]=max(dp[v],dp[v-w[i]]+c[i]); 47 printf("%d",dp[vmax]); 48 return 0; 49 }