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

2 years ago
#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;
}