You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

66 lines
2.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
const int N = 10005;
int w[N]; //价钱
int d[N]; //价值(美丽值)
int f[N];
int dp[N];
//并查集
int find(int x) {
if (f[x] == x) return x;
return f[x] = find(f[x]);
}
// 【解题思路】
// 并查集+01背包都是基本算法╮(╯▽╰)╭
// 先读进来那一堆价格和价值,然后读进来他们的关系,把有关系的两个合并在一个集合里。
// 做完并查集了之后把相同代表元素的价格加在一起,价值加在一起,我们就得到了数量<=n的物品可以做一次01背包就能求出题目要求的解
// 题解:利用并查集把必须一起购买的合并到一起,然后 将一个集合中的物品看做一个物品变成经典的01背包问题。
int main() {
//输入+输出重定向
freopen("../1414.txt", "r", stdin);
int n, m, v; //nmv表示n朵云m个搭配Joe有v的钱。
cin >> n >> m >> v;
for (int i = 1; i <= n; i++) {
f[i] = i;//每个人都是自己的爸爸
cin >> w[i] >> d[i]; //每行widi表示i朵云的价钱和价值(美丽值)。
}
//读取它们之间的关系,把有关系的两个合并在一个集合里。
int x, y;
while (m--) {
cin >> x >> y;
int a = find(x), b = find(y);
if (a != b) {
f[b] = a; //a是老大b里面记录它是a的孩子
w[a] += w[b]; //它爸爸管理价格,它自己没有资格参加
d[a] += d[b]; //它爸爸管理价值(美丽值),它自己没有资格参加
}
}
//
// cout << "打印w数组进行调试" << endl;
// for (int i = 1; i <= n; i++) cout << w[i] << " ";
// cout << endl;
// cout << "打印d数组进行调试" << endl;
// for (int i = 1; i <= n; i++) cout << d[i] << " ";
// cout << endl;
//01背包
for (int i = 1; i <= n; i++) {
if (f[i] == i) //如果有权利参加的爸爸们!
for (int j = v; j >= w[i]; j--) {
dp[j] = max(dp[j], dp[j - w[i]] + d[i]);
}
}
cout << dp[v];
//关闭文件
fclose(stdin);
return 0;
}