Files
python/TangDou/AcWing_TiGao/T4/1252_ErWei.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

70 lines
2.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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,肯定不会在内存上出问题。
总结:
(1)01背包一维相比二维,能够节约非常大的空间,二维特别容易MLE。
(2)01背包一维相比二维,不用考虑上一个依赖是不是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;
}