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

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

4个月前 (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),适用于稀疏图,通过贪心策略保证解的最优性。代码实现简洁高效,并查集的路径压缩优化进一步降低查找时间。理解此算法有助于解决类似连通性与最小权值问题,为算法学习打下坚实基础。

原创内容 转载请注明出处

分享给朋友:

相关文章

手搓邻接矩阵类代码注释与实现指南:从零开始理解图论数据结构(适合小白)

一、简介和特点邻接矩阵是用于表示图(Graph)的一种数据结构,通常用二维数组存储节点之间的关系。本文的graph类通过C++实现了一个基础的邻接矩阵结构,特点如下:1. 动态创建:根据用户输入的节点...

洛谷P4551题解题报告:图论与Trie树优化异或路径问题的实战解析

洛谷P4551题解题报告:图论与Trie树优化异或路径问题的实战解析

一、题目解读洛谷P4551题要求在一个无向图中,寻找任意两点路径权值异或后的最大值。题目输入为图的边信息(点数n和n-1条边),每条边包含起点、终点及权值。需输出所有路径中权值异或的最大值。问题核心在...

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

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

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

力扣3112题解法:带时间限制的最短路径问题解析(C++代码)

力扣3112题解法:带时间限制的最短路径问题解析(C++代码)

一、题目解读力扣3112题要求解决带时间限制的最短路径问题:给定一个有向图,节点具有消失时间,需计算从起点到各节点的最短路径,且路径总时间不能超过节点的消失时间。题目难点在于需在传统最短路径算法(如D...

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

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

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

【NOI 2002】银河英雄传说(洛谷P1196)题解:并查集优化路径压缩算法详解

【NOI 2002】银河英雄传说(洛谷P1196)题解:并查集优化路径压缩算法详解

一、题目解读“银河英雄传说”是一道经典的动态集合合并问题。题目背景设定在星际战争中,要求处理两种指令:战舰合并(M)和距离查询(C)。需要维护多个战舰集合,支持快速合并操作,并计算同一集合内任意两战舰...

发表评论

访客

看不清,换一张

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