洛谷1455 搭配购买
本题地址: http://www.luogu.org/problem/show?pid=1455
题目描述
明天就是母亲节了,电脑组的小朋友们在忙碌的课业之余挖空心思想着该送什么礼物来表达自己的心意呢?听说在某个网站上有卖云朵的,小朋友们决定一同前往去看看这种神奇的商品,这个店里有n朵云,云朵已经被老板编号为1,2,3,……,n,并且每朵云都有一个价值,但是商店的老板是个很奇怪的人,他会告诉你一些云朵要搭配起来买才卖,也就是说买一朵云则与这朵云有搭配的云都要买,电脑组的你觉得这礼物实在是太新奇了,但是你的钱是有限的,所以你肯定是想用现有的钱买到尽量多价值的云。
输入输出格式
输入格式:
第1行n,m,w,表示n朵云,m个搭配和你现有的钱的数目
第2行至n+1行,每行ci,di表示i朵云的价钱和价值
第n+2至n+1+m ,每行ui,vi表示买ui就必须买vi,同理,如果买vi就必须买ui
输出格式:
一行,表示可以获得的最大价值
输入输出样例
输入样例#1:
5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2
输出样例#1:
1
说明
30%的数据满足:n<=100
50%的数据满足:n<=1000;m<=100;w<=1000;
100%的数据满足:n<=10000;0<=m<=5000;w<=10000.
【思路】
并查集+01背包。
相互依赖的物品就是一个连通块,并查集构造出每个互相依赖的物品包的重量与价值,01背包即可。
由此见,并查集可以用来处理图上的连通问题。
【代码】
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 5 const int maxn = 10000+10; 6 7 int p[maxn],sumw[maxn],sumc[maxn]; 8 int w[maxn],c[maxn],f[maxn]; 9 int n,m,C; 10 11 int find(int x) { 12 return x==p[x]?x:p[x]=find(p[x]); 13 } 14 15 int main() { 16 scanf("%d%d%d",&n,&m,&C); 17 for(int i=1;i<=n;i++) 18 scanf("%d%d",&sumw[i],&sumc[i]),p[i]=i; 19 int u,v; 20 for(int i=0;i<m;i++) { 21 scanf("%d%d",&u,&v); 22 int x=find(u),y=find(v); 23 if(x!=y) { 24 p[x]=y; 25 sumw[y]+=sumw[x]; 26 sumc[y]+=sumc[x]; 27 } 28 } 29 int cnt=0; 30 for(int i=1;i<=n;i++) if(p[i]==i){ 31 ++cnt; 32 w[cnt]=sumw[i]; 33 c[cnt]=sumc[i]; 34 } 35 for(int i=1;i<=cnt;i++) 36 for(int j=C;j>=w[i];j--) 37 f[j]=max(f[j],f[j-w[i]]+c[i]); 38 printf("%d ",f[C]); 39 return 0; 40 }