洛谷 P1455 搭配购买

 

输入输出样例

输入 #1复制

5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2

输出 #1复制

1

说明/提示

  • 对于 30\%30% 的数据,满足 1 \le n \le 1001≤n≤100;
  • 对于 50\%50% 的数据,满足 1 \le n,w \le 10^31≤n,w≤103,1 \le m \le 1001≤m≤100;
  • 对于 100\%100% 的数据,满足 1 \le n \le 10^41≤n≤104,0 \le m \le 5 \times 10^30≤m≤5×103。

思路:这一题其实是由并查集和动态规划01背包结合起来的题目,难度适中吧.

相信学过并查集的应该很容易理解,我们现将每一个云朵的根节点设置为自身,然后输入搭配在一起的云朵,并将后面的棉花设置为前面的云朵的根节点(反过来也行哦),然后将根节点的云朵的总价格和总价值更新(加上搭配在一起的云朵的价格和价值)将所有搭配类型循环完之后,就可以套用01背包的模板了只不过加了一个约束条件,就是判断云朵是否属于根节点如果属于根节点则进行动态规划,不是根节点的话则进入下一个云朵。

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 5;
const int M = 5e3 + 5;
int c[N], d[N], dp[N], f[N];
int find(int x)
{
    return f[x] == x ? x : f[x] = find(f[x]);//查找找根节点
}
int main()
{
    ios::sync_with_stdio(false);//给cin提速 因为cin比scanf慢
    cin.tie(0), cout.tie(0);
    int n, m, w;
    cin >> n >> m >> w;
    for (int i = 1; i <= n; i++)
    {
        cin >> c[i] >> d[i];
        f[i] = i;//令自身为根节点
    }
    int x, y;
    for (int i = 1; i <= m; i++)
    {
        cin >> x >> y;
        int u = find(x);//并查集合并
        int v = find(y);
        f[u] = v;
        c[v] = c[u] + c[v];//将搭配的总价格和总价值放置于根节点处
        d[u] = d[u] + d[v];
    }
    for (int i = 1; i <= n; i++)//搜寻根节点,如果为根节点则进行动态规划
    {
        if (f[i] == i)
        {
            for (int j = w; j >= c[i]; j--)
            {
                dp[j] = max(dp[j], dp[j - c[i]] + d[i]);
            }
        }
    }
    cout << dp[w];//输出最大的价值
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值