洛谷P1455 搭配购买
1 //并查集+01背包 2 //用并查集把几件物品合为一件 3 #include<bits/stdc++.h> 4 using namespace std; 5 const int maxn=10005; 6 const int maxv=10005; 7 int n,m,v_tot,tot,v[maxn],w[maxn],dp[maxv]; 8 struct node{ 9 int fa,cnt,v_sum,w_sum; 10 }f[maxn]; 11 int find(int x) 12 { 13 if(f[x].fa==x) return x; 14 return f[x].fa=find(f[x].fa); 15 } 16 void Union(int x,int y)//合并时把体积和价值也合并 17 { 18 int fax=find(x),fay=find(y); 19 if(fax==fay) return; 20 if(f[fax].cnt<=f[fay].cnt) {f[fax].fa=fay;f[fay].cnt+=f[fax].cnt;f[fay].v_sum+=f[fax].v_sum;f[fay].w_sum+=f[fax].w_sum;} 21 else {f[fay].fa=fax;f[fax].cnt+=f[fay].cnt;f[fax].v_sum+=f[fay].v_sum;f[fax].w_sum+=f[fay].w_sum;} 22 find(x),find(y);//合并完需要再路径压缩 23 } 24 void init()//并查集初始化 25 { 26 for(int i=1;i<=n;++i) 27 f[i].fa=i,f[i].cnt=1, 28 f[i].v_sum=v[i],f[i].w_sum=w[i]; 29 } 30 int main() 31 { 32 scanf("%d%d%d",&n,&m,&v_tot); 33 for(int i=1;i<=n;++i) scanf("%d%d",&v[i],&w[i]); 34 init(); 35 for(int i=1,x,y;i<=m;++i) scanf("%d%d",&x,&y),Union(x,y); 36 for(int i=1;i<=n;++i) 37 if(find(i)==i) v[++tot]=f[i].v_sum,w[tot]=f[i].w_sum; 38 for(int i=1;i<=tot;++i) 39 for(int j=v_tot;j>=v[i];--j) 40 dp[j]=max(dp[j],dp[j-v[i]]+w[i]); 41 printf("%d",dp[v_tot]); 42 return 0; 43 }