1387:搭配购买(buy)

【题目描述】

Joe觉得云朵很美,决定去山上的商店买一些云朵。商店里有n朵云,云朵被编号为1,2,…...,n,并且每朵云都有一个价值。但是商店老板跟他说,一些云朵要搭配来买才好,所以买一朵云则与这朵云有搭配的云都要买。

但是Joe的钱有限,所以他希望买的价值越多越好。

【输入】

第1行n,m,w,表示n朵云,m个搭配,Joe有w的钱。

第2~n+1行,每行ci,di表示i朵云的价钱和价值。

第n+2~n+1+m行,每行ui,vi,表示买ui就必须买vi,同理,如果买vi就必须买ui。

【输出】

一行,表示可以获得的最大价值。

【输入样例】

5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2

【输出样例】

1

【提示】

【数据范围】

30%的数据保证:n≤100

50%的数据保证:n≤1,000;m≤100;w≤1,000

100%的数据保证:n≤10,000;0≤m≤5000;w≤10,000

这题就是 并查集和01背包的组合出来的题,首先要把搭配一起的用并查集组合起来,那么最后求出的物品数量肯定<=n

注意在用结构体把值赋值给w v时一定要先路径压缩一下,这样就是父节点就是一个值了

很有意思的一题

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e4 + 10;
int p[N];
int w[N];
int c[N];
int f[N];
int n, m, s;
struct node
{
	int c;
	int w;
	bool flag;
}num[N];

int findth(int x)
{
	if (x == p[x]) return x;
	return p[x] = findth(p[x]);
}

void unionn(int x, int y)
{
	int xx = findth(x);
	int yy = findth(y);
	if (xx != yy) p[yy] = xx;
}
int cnt;
int ci[N];
int di[N];

int main()
{
	scanf("%d %d %d", &n, &m, &s);
	for (int i = 1;i <= n;i++) p[i] = i;
	for (int i = 1;i <= n;i++) {
		scanf("%d %d", &ci[i], &di[i]);
	}

	for (int i = 1;i <= m;i++) {
		int x, y;
		scanf("%d %d", &x, &y);
		unionn(x, y);
	}

    for (int i = 1;i <= n;i++) {
		findth(i);
	}

	for (int i = 1;i <= n;i++) {
		num[p[i]].w += ci[i];
		num[p[i]].c += di[i];
		num[p[i]].flag = true;
	}

	
	
	for (int i=1;i<=n;i++){
		if (num[i].flag) {
			w[++cnt] = num[i].w;
			c[cnt] = num[i].c;
		}
	}

	for (int i = 1;i <= cnt;i++) {
		for (int j = s;j >= w[i];j--) {
			f[j] = max(f[j], f[j - w[i]] + c[i]);
		}
	}

	printf("%d\n", f[s]);

	return 0;
}

猜你喜欢

转载自blog.csdn.net/Wchenchen0/article/details/81588263
今日推荐