当前位置:首页 > 洛谷 > 洛谷P1195题解析:Kruskal算法构建K个连通分量的优化解法

洛谷P1195题解析:Kruskal算法构建K个连通分量的优化解法

3个月前 (09-13)

洛谷P1195题解析:Kruskal算法构建K个连通分量的优化解法 Kruskal算法 并查集 最小生成树 连通分量 C++ 图论 第1张

一、题目解读

洛谷P1195题要求处理一个图论问题:给定N朵云和M条边,每条边连接两朵云并附带代价,需通过添加边将云朵分组,使得最终形成K个连通分量,且总代价最小。若无法恰好形成K个连通分量,则输出“No Answer”。题目核心在于利用最小生成树的思想,在限定连通分量数量下求解最优解。

二、解题思路

采用Kruskal算法并查集的结合。首先对所有边按代价升序排序,随后通过并查集维护连通分量。遍历每条边时,若合并后能减少连通分量数量且不超出K的限制,则加入该边并累加代价。关键在于利用路径压缩优化并查集查找,降低时间复杂度。

三、解题步骤

1. 输入云朵数N、边数M、目标连通分量数K。

2. 初始化并查集数组(每个云朵自成连通分量)。

3. 读取所有边存入结构体中,按代价排序。

4. 循环遍历边:

○ 若当前连通分量数已≤K,跳出循环。

○ 通过find()函数查找两云朵的根节点,若不同则合并,更新总代价及连通分量数。

5. 检查最终连通分量数是否等于K,输出总代价或“No Answer”。

四、代码及注释

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

// 定义边的结构体
struct Edge {
    int x, y, l; // x和y表示云朵编号,l表示连接代价
    bool operator<(const Edge& other) const {
        return l < other.l; // 按代价从小到大排序
    }
};

vector<Edge> edges; // 存储所有边
vector<int> parent; // 并查集数组

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

int main() {
    int N, M, K;
    cin >> N >> M >> K;
    
    // 初始化并查集
    parent.resize(N+1);
    for (int i = 1; i <= N; ++i) {
        parent[i] = i;
    }
    
    // 读取所有边
    edges.resize(M);
    for (int i = 0; i < M; ++i) {
        cin >> edges[i].x >> edges[i].y >> edges[i].l;
    }
    
    // 按边权从小到大排序
    sort(edges.begin(), edges.end());
    
    int totalCost = 0;
    int connectedComponents = N; // 初始时每个云朵自成一个连通分量
    
    // Kruskal算法构建最小生成森林
    for (const auto& e : edges) {
        if (connectedComponents <= K) break; // 已经形成K个连通分量
        
        int rootX = find(e.x);
        int rootY = find(e.y);
        
        if (rootX!= rootY) { // 如果不在同一个连通分量
            parent[rootY] = rootX; // 合并
            totalCost += e.l;
            connectedComponents--; // 连通分量减少1
        }
    }
    
    // 检查是否能形成K个棉花糖
    if (connectedComponents == K) {
        cout << totalCost << endl;
    } else {
        cout << "No Answer" << endl;
    }
    
    return 0;
}

五、总结

该解法通过Kruskal算法的贪心策略,确保每次合并边时总代价最小,同时利用并查集高效维护连通性。时间复杂度O(ElogE)由排序主导,适用于稀疏图场景。当目标连通分量数K较小时,该算法能快速得到最优解,是解决此类问题的经典思路。

原创内容 转载请注明出处

分享给朋友:

相关文章

力扣94:递归之美 轻松掌握二叉树中序遍历

力扣94:递归之美 轻松掌握二叉树中序遍历

题目解读二叉树的中序遍历是一种基础且重要的树遍历方式,其遍历顺序为:先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树。对于二叉搜索树,中序遍历的结果恰好是节点值的升序排列。给定一个二叉...

牛客NC67题解:汉诺塔递归算法与解题步骤

牛客NC67题解:汉诺塔递归算法与解题步骤

一、题目解读牛客NC67题要求解决汉诺塔问题,这是一个经典的递归算法题目。题目给定整数n,代表汉诺塔中的盘子数量,需要输出将n个盘子从起始柱移动到目标柱的所有步骤。汉诺塔问题规则为:每次只能移动一个盘...

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

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

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

洛谷2652题解析:同花顺排序问题的动态规划与滑动窗口优化

洛谷2652题解析:同花顺排序问题的动态规划与滑动窗口优化

一、题目解读洛谷2652题要求对一组扑克牌进行排序,目标是找到最少需要调整的次数,使得所有牌形成同花顺。题目中,扑克牌由花色和数字组成,需先按花色排序,再在同花色内按数字排序。核心难点在于如何处理花色...

牛客232639题解析:双指针+排序算法高效求解三角形数量(附代码详解)

牛客232639题解析:双指针+排序算法高效求解三角形数量(附代码详解)

一、题目解读牛客232639题要求计算一个整数数组中能够组成有效三角形的三边组合数量。根据三角形不等式,三边需满足任意两边之和大于第三边。例如,数组[3, 4, 5, 6]可组成两个有效三角形([3,...

力扣LCR074题区间合并算法解析:贪心排序与区间重叠处理

力扣LCR074题区间合并算法解析:贪心排序与区间重叠处理

一、题目解读力扣LCR074题要求对给定的二维区间数组(每个区间由起始点和终止点构成)进行合并,将重叠的区间合并为更宽的区间,最终输出不重叠的合并结果。例如,输入[[1,3],[2,6],[8,10]...

发表评论

访客

看不清,换一张

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