当前位置:首页 > 牛客 > 牛客4633题:Kruskal算法求解最小生成树问题

牛客4633题:Kruskal算法求解最小生成树问题

2个月前 (08-09)

牛客4633题:Kruskal算法求解最小生成树问题 牛客题解 Kruskal算法 并查集 最小生成树 图论算法 稀疏图 贪心策略 第1张

一、题目解读

牛客4633题要求求解一个带权无向图中的最小生成树,并输出其最大边权值。题目核心在于构建一棵包含所有节点且总权值最小的生成,需判断是否存在合法解,若不存在则返回-1。问题本质属于图论中的最小生成树问题,可通过Kruskal算法高效解决。

二、解题思路

采用Kruskal算法,结合并查集检测环路。首先对边按权值升序排序,依次遍历边:若连接的两个节点不在同一集合(即不构成环路),则合并集合并记录当前边权值。当合并的边数达到n-1时(形成生成树),退出循环。最终输出最大边权或-1。该思路利用贪心策略,每次选择最小权值的可行边,避免生成树权值增大。

三、解题步骤

1. 输入与初始化:读取节点数N和边数M,创建Edge数组存储边信息,初始化并查集UnionFind(N个独立节点)。

2. 边排序:按边权值升序排序edges,确保后续处理优先选择小权值边。

3. Kruskal核心逻辑:遍历排序后的边,对每条边(u,v):

○ 通过find()获取u和v的根节点,若不同则合并(unite返回true),更新最大边权maxWood并计数边数edgeCount。

○ 当边数达到N-1时,生成树已形成,退出循环。

4. 结果判断:若edgeCount = N-1,输出maxWood;否则说明无合法生成树,输出-1。

四、代码与注释

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

// 并查集数据结构用于检测环路
struct UnionFind {
    vector<int> parent;
    UnionFind(int n) : parent(n+1) {
        for(int i = 1; i <= n; ++i) // 初始化每个节点为独立集合
            parent[i] = i;
    }
    int find(int x) { // 路径压缩优化查找
        if(parent[x]!= x)
            parent[x] = find(parent[x]);
        return parent[x];
    }
    bool unite(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if(rootX == rootY) return false; // 已连通,存在环
        parent[rootY] = rootX; // 合并集合
        return true;
    }
};

struct Edge {
    int u, v, weight;
    bool operator<(const Edge& other) const {
        return weight < other.weight; // 按权值排序
    }
};

int main() {
    int N, M;
    cin >> N >> M; // 输入节点数和边数

    vector<Edge> edges(M);
    for(int i = 0; i < M; ++i)
        cin >> edges[i].u >> edges[i].v >> edges[i].weight; // 读入边信息

    // Kruskal算法核心步骤
    sort(edges.begin(), edges.end()); // 边排序
    UnionFind uf(N);
    int maxWood = 0, edgeCount = 0;
    for(const auto& e : edges) {
        if(uf.unite(e.u, e.v)) { // 合并可行边
            maxWood = max(maxWood, e.weight);
            if(++edgeCount == N - 1) break; // 生成树形成,退出
        }
    }
    cout << (edgeCount == N - 1? maxWood : -1) << endl; // 输出结果
    return 0;
}

五、总结

本文通过牛客4633题实战,展示了Kruskal算法结合并查集求解最小生成树的经典应用。该算法时间复杂度O(ElogE),适用于稀疏图,通过贪心策略保证解的最优性。代码实现简洁高效,并查集的路径压缩优化进一步降低查找时间。理解此算法有助于解决类似连通性与最小权值问题,为算法学习打下坚实基础。

原创内容 转载请注明出处

分享给朋友:

相关文章

牛客14496题解:括号最大深度问题(栈思想与代码优化)

牛客14496题解:括号最大深度问题(栈思想与代码优化)

一、题目解读牛客14496题要求计算给定括号字符串中的最大深度。例如,对于字符串 "(()())",最大深度为2。题目考察对括号嵌套结构的理解,以及如何通过编程找到最深嵌套层次。二...

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

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

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

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

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

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

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

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

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

洛谷P3393题解:基于多源BFS与Dijkstra算法求解图论最小花费路径问题

洛谷P3393题解:基于多源BFS与Dijkstra算法求解图论最小花费路径问题

一、题目解读洛谷P3393题要求在一个包含N个城市和M条双向道路的图中,求解从起点1到终点N的最小花费路径。图中存在僵尸城市(僵尸无法通过)和危险城市(由僵尸城市扩散S步后标记),需要避开所有危险城市...

牛客4577题解:滑动窗口解法

牛客4577题解:滑动窗口解法

一、题目解读牛客4577题要求处理多组测试数据,每组包含一个整数数组crimes和两个参数n(数组长度)、t(阈值)、c(窗口大小)。题目需要统计数组中所有长度恰好为c的子数组,其元素和不超过t的数量...

发表评论

访客

看不清,换一张

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