搭配购买 解题报告

搭配购买

Problem Description

Joe觉得云朵很美,决定去山上的商店买一些云朵。商店里有n朵云,云朵被编号为1,2,...,n,并且每朵云都有一个价值。但是商店老板跟他说,一些云朵要搭配来买才好,所以买一朵云则与这朵云有搭配的云都要买。但是Joe的钱有限,所以他希望买的价值越多越好。
Input
输入有多组数据,每组数据第1行、m、w,表示n朵云,m个搭配,Joe有w的钱。
第2至n+1行,每行ci、di表示i朵云的价钱和价值。
第n+2至n+1+m行,每行ui、vi表示买ui就必须买vi,同理,如果买vi就必须买ui。
Output
对于每组数据,输出一行,表示可以获得的最大价值。
Sample Input
5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2
Sample Output

1

【数据范围】

30%的数据满足:n<=100;

50%的数据满足:n<=1000;m<=100;w<=1000;

100%的数据满足:n<=10000;0<=m<=5000;w<=10000。

【解题思路】

并查集+01背包,都是基本算法╮(╯▽╰)╭

先读进来那一堆价格和价值,然后读进来他们的关系,把有关系的两个合并在一个集合里。做完并查集了之后把相同代表元素的价格加在一起,价值加在一起,我们就得到了数量<=n的物品,可以做一次01背包,就能求出题目要求的解;

【代码】

#include
#include
#include
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]
【犯的错误】

数组开小了。。。以后再有这么低级的bug我就。。。

你可能感兴趣的:(题解,dp,并查集)