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.

70 lines
2.3 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 = 10010;
int n, m, sum; //有 n 朵云m 个搭配Joe有 sum 的钱。
int v[N], w[N]; //表示 i 朵云的价钱和价值
int p[N];
int f[N][N];
/*过掉7/11个数据无法AC
原因分析f[N][N]第一维是可以选择的物品个数上限是10000
第二维是可以支付的钱数上限也是10000
如果按二维思路来处理确实需要一个10000*10000的数组
10000*10000*8= 800000000 byte
800000000/1024/1024= 762MB 本题上限是64MB妥妥的超内存,MLE~
穷则思变既然int+二维过不了那么试试short吧因为short最大是65536,符合题意,
并且只占两个bit,就是10000*10000*2= 200000000 byte
200000000/1024/1024= 190MB 本题上限是64MB妥妥的超内存,MLE~
那么一维的为什么可以呢?
一维的只有10000*8=80000 byte
80000/1024/1024=0.076MB 本题上限是64MB肯定不会在内存上出问题。
总结:
101背包一维相比二维能够节约非常大的空间二维特别容易MLE。
201背包一维相比二维不用考虑上一个依赖是不是i-1行的问题不用特殊用last方式
记录并处理,出错概率小
*/
//最简并查集
int find(int x) {
if (p[x] != x) p[x] = find(p[x]); //路径压缩
return p[x];
}
int main() {
cin >> n >> m >> sum;
//实始化并查集
for (int i = 1; i <= n; i++) p[i] = i;
//读入每个云朵的价钱(体积)和价值
for (int i = 1; i <= n; i++) cin >> v[i] >> w[i];
while (m--) {
int a, b;
cin >> a >> b; //两种云朵需要一起买
int pa = find(a), pb = find(b);
if (pa != pb) {
//集合有两个属性总价钱、总价值都记录到root节点上
v[pb] += v[pa];
w[pb] += w[pa];
p[pa] = pb;
}
}
// 01背包
int last = 0;
for (int i = 1; i <= n; i++)
if (p[i] == i) { //因处理集合的代表元素
for (int j = 1; j <= sum; j++) {
f[i][j] = f[last][j];
if (v[i] <= j)
f[i][j] = max(f[i][j], f[last][j - v[i]] + w[i]);
}
last = i; //依赖的上一个状态
}
printf("%d\n", f[n][sum]);
return 0;
}