Luogu P1455 搭配购买 题解

题目传送门:

Luogu P1455

思路:

这个题目的思路还算简单,就是用并查集来维护那些云要一起买。之后将要在一起买的云合并成一朵大云。之后就是一个简单的01背包问题了。

要注意的地方:

这个题目我居然WA了好几次,每次都是因为在枚举每个云判断是否属于同一个云的时候,没有将 f[i] 更新为 f[i] 的父亲导致 f[i] 中存的不是 \(i\) 所在的连通块的根。然后就WA了。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 1e4 + 5;

int n, m, v;
int a, b;
int c[N], w[N];
int f[N]; //并查集
int dp[N];

int read() {
    int s = 0, w = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        s = s * 10 + ch - '0';
        ch = getchar();
    }
    return s * w;
}

void write(int x) {
    if (x < 0) putchar('-'), x = -x;
    if (x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

int get_f(int v) {
    if (f[v] == v) return v;
    else return f[v] = get_f(f[v]);
}

inline int Max(int x, int y) {
    return x >= y ? x : y;
}

int main(int argc, char const *argv[]) {
    n = read(), m = read(), v = read();
    for (register int i = 1; i <= n; ++i) {
        c[i] = read(), w[i] = read();
        f[i] = i; //初始化并查集
    }
    for (register int i = 1; i <= m; ++i) {
        a = read(), b = read();
        int t1 = get_f(a);
        int t2 = get_f(b);
        if (t1 != t2) f[t1] = t2;
    }
    for (register int i = 1; i <= n; ++i) {
        f[i] = get_f(i);
        if (f[i] != i) {
            c[f[i]] += c[i];
            w[f[i]] += w[i];
            c[i] = 0;
            w[i] = 0;
        }
    }
    for (register int i = 1; i <= n; ++i) {
        for (register int j = v; j >= c[i]; --j) {
            dp[j] = Max(dp[j], dp[j - c[i]] + w[i]);
        }
    }
    write(dp[v]), putchar('\n');
    return 0;
}

转载于:https://www.cnblogs.com/lixiao189/p/9831996.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值