当前位置:首页 > 洛谷 > 洛谷P1194题:利用Kruskal算法求解商品优惠组合问题

洛谷P1194题:利用Kruskal算法求解商品优惠组合问题

2个月前 (08-04)

洛谷P1194题:利用Kruskal算法求解商品优惠组合问题 洛谷题解 Kruskal算法 最小生成树 并查集 C++ 路径压缩 图论 第1张

一、题目解读

洛谷P1194题要求计算在给定商品单价及优惠组合价格的情况下,购买所有商品的最小总价。题目关键在于如何处理优惠关系,并将其转化为图论中的边权重问题,进而通过算法寻找最优解。

二、解题思路

采用经典的Kruskal算法求解最小生成树。核心思路如下:

1. 虚拟节点构建:引入节点0作为“起点”,与所有商品建立边,权重为商品单价,将问题转化为从0出发覆盖所有节点的最小路径和。

2. 优惠边筛选:仅保留i<j的优惠边(避免重复),降低计算复杂度。

3. Kruskal算法:对边按权重排序,通过并查集逐步合并连通分量,直至生成包含B条边的

三、解题步骤

1. 输入与初始化:读入商品数量B和单价A,初始化边集edges及并查集parent。

2. 构建虚拟边:添加{0,i,A}边至edges,确保每个商品与虚拟节点相连。

3. 读入优惠边:若i<j且存在优惠价格k,添加{i,j,k}至edges。

4. 排序与Kruskal:

    按边权重排序edges。

    遍历边集,若合并u和v节点未形成环,则计入总价并更新并查集。

    当连通分量达到B时终止,总价为最小生成树权重。

四、代码与注释

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// 边结构(节点u,v,权重w)
struct Edge {
    int u, v, w;
    bool operator<(const Edge& other) const {
        return w < other.w;   // 按权重排序
    }
};

vector<int> parent;   // 并查集父节点数组

// 并查集查找根节点
int find(int x) {
    return parent[x] == x? x : parent[x] = find(parent[x]);  // 路径压缩
}

int main() {
    int A, B;   // A:商品单价,B:商品数量
    cin >> A >> B;
    
    vector<Edge> edges;   // 存储所有边
    
    // 步骤2:添加虚拟节点0到各商品的边
    for (int i = 1; i <= B; ++i) {
        edges.push_back({0, i, A});
    }
    
    // 步骤3:读入优惠价格
    for (int i = 1; i <= B; ++i) {
        for (int j = 1; j <= B; ++j) {
            int k;
            cin >> k;
            if (i < j && k!= 0) {  // 避免重复添加
                edges.push_back({i, j, k});
            }
        }
    }
    
    // Kruskal算法准备
    sort(edges.begin(), edges.end());   // 步骤4:排序
    parent.resize(B + 1);  
    for (int i = 0; i <= B; ++i) parent[i] = i;   // 初始化并查集
    
    int total = 0, count = 0;
    for (auto& e : edges) {
        int rootU = find(e.u);
        int rootV = find(e.v);
        if (rootU!= rootV) {
            parent[rootV] = rootU;   // 合并节点
            total += e.w;
            if (++count == B) break;  // 生成树有B条边
        }
    }
    
    cout << total << endl;
    return 0;
}

五、总结

本解法通过巧妙引入虚拟节点,将商品购买问题转化为最小生成树问题,结合Kruskal算法高效求解。关键在于:

1. 利用并查集优化连通性判断,避免重复计算。

2. 边权重排序与剪枝(仅保留i<j的优惠边)降低时间复杂度。

3. 路径压缩优化并查集查询效率,提升整体性能。


原创内容 转载请注明出处

分享给朋友:

相关文章

NOIP2005 普及组 洛谷P1408 背包问题的空间优化技巧与实战应用

NOIP2005 普及组 洛谷P1408 背包问题的空间优化技巧与实战应用

题目重解想象你是一名药师,有t分钟在山上采集m种草药。每种草药需要time分钟采集,价值为num。这就像考试时分配时间做题,要选择收益最大的题目组合。题目要求计算在规定时间内能获得的最大草药价值。解题...

洛谷1111题解题全解析:基于Kruskal算法与并查集的最小生成树实现

洛谷1111题解题全解析:基于Kruskal算法与并查集的最小生成树实现

一、题目解读洛谷1111题是一道经典的图论问题,要求构建一个无向图的最小生成树,并输出其最大边权值。题目核心在于通过给定的边集合,找到连接所有节点的最小权值子集,同时保证无环。这通常涉及最小生成树算法...

【洛谷1184题解析】用C++高效解决地点匹配问题(附代码与解题思路)

【洛谷1184题解析】用C++高效解决地点匹配问题(附代码与解题思路)

一、题目解读洛谷1184题要求处理一组地点列表与行程记录,统计其中匹配的天数。题目难点在于高效处理带有空格的字符串输入,以及快速判断每日行程是否在高手可去地点集合中。需要兼顾输入格式解析与算法效率。二...

洛谷1656题解:基于Tarjan算法求解割边问题(附代码与详细步骤)

洛谷1656题解:基于Tarjan算法求解割边问题(附代码与详细步骤)

一、题目解读洛谷1656题要求在无向图中找出所有割边(即删除后导致图不连通的边)。题目核心在于判断图的连通性,并识别哪些边是“桥”。需理解图论中的连通分量概念,以及如何通过算法高效定位割边。二、解题思...

洛谷P2190题解:铁路售票系统车厢计算(差分数组+前缀和优化)

洛谷P2190题解:铁路售票系统车厢计算(差分数组+前缀和优化)

一、题目解读洛谷P2190题要求解决铁路售票系统中的车厢数量计算问题。题目给定n个车站和m条订票申请,每条申请包含区间[x,y)及乘客数z。需要计算在不超载的情况下(每节车厢最多36人),满足所有乘客...

洛谷P1121题解:动态规划求解环形数组最大子段和问题(附代码注释)

洛谷P1121题解:动态规划求解环形数组最大子段和问题(附代码注释)

一、题目解读洛谷P1121题要求求解环形数组的最大子段和,即在一个环形数组中找到一个连续子段,使其元素和最大。环形数组的特殊性在于首尾元素可相连,需考虑线性子段与跨越首尾的环形子段两种情况。二、解题思...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。