搭配购买
Problem Description
Joe觉得云朵很美,决定去山上的商店买一些云朵。商店里有n朵云,云朵被编号为1,2,...,n,并且每朵云都有一个价值。但是商店老板跟他说,一些云朵要搭配来买才好,所以买一朵云则与这朵云有搭配的云都要买。但是Joe的钱有限,所以他希望买的价值越多越好。1
【数据范围】
30%的数据满足:n<=100;
50%的数据满足:n<=1000;m<=100;w<=1000;
100%的数据满足:n<=10000;0<=m<=5000;w<=10000。
【解题思路】
并查集+01背包,都是基本算法╮(╯▽╰)╭
先读进来那一堆价格和价值,然后读进来他们的关系,把有关系的两个合并在一个集合里。做完并查集了之后把相同代表元素的价格加在一起,价值加在一起,我们就得到了数量<=n的物品,可以做一次01背包,就能求出题目要求的解;
【代码】
<span style="font-size:14px;">#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,m,mon,i,j,k,v,ui,vi; int f[10005],f1[10005],w[10005],c[10005],ci[10005],di[10005]; struct hp { int w,c; bool pd; }b[10005]; int find(int x) { if (f[x]==x) return f[x]; f[x]=find(f[x]); return f[x]; } void merge(int x,int y) { int n1=find(x); int n2=find(y); f[n1]=n2; return; } int main() { freopen("buy.in","r",stdin); freopen("buy.out","w",stdout); scanf("%d%d%d",&n,&m,&mon); for (i=1;i<=n;++i) scanf("%d%d",&ci[i],&di[i]); for (i=1;i<=n;++i) f[i]=i; for (i=1;i<=m;++i) { scanf("%d%d",&ui,&vi); merge(ui,vi); } for (i=1;i<=n;++i) k=find(i); for (i=1;i<=n;++i) { b[f[i]].pd=true; b[f[i]].w+=ci[i]; b[f[i]].c+=di[i]; } k=0; for (i=1;i<=n;++i) if (b[i].pd) { w[++k]=b[i].w; c[k]=b[i].c; } n=k; for (i=1;i<=n;++i) for (v=mon;v>=w[i];--v) if (f1[v]<f1[v-w[i]]+c[i]) f1[v]=f1[v-w[i]]+c[i]; printf("%d",f1[mon]); return 0; }</span>【犯的错误】
数组开小了。。。以后再有这么低级的bug我就。。。