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

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

1天前

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

原创内容 转载请注明出处

分享给朋友:

相关文章

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

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

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

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

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

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

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

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

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

【力扣2846题】图论+二进制提升:高效解决连通性问题(附C++代码)

【力扣2846题】图论+二进制提升:高效解决连通性问题(附C++代码)

一、题目解读力扣2846题要求解决一个基于图连通性的操作优化问题。给定一个无向图,包含边权重,以及一系列查询,每个查询询问两点间路径的最小操作次数。题目关键在于高效计算路径上权重分布的统计信息,并转化...

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

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

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

NOI 2001密码锁(洛谷P2024)解题全解析:并查集+关系标记算法实战

NOI 2001密码锁(洛谷P2024)解题全解析:并查集+关系标记算法实战

一、题目解读2001年NOI密码锁(洛谷P2024)是一个经典的逻辑判断问题。题目描述了一个动物园中动物之间的关系,需要处理两种类型的陈述:同类关系(1)和捕食关系(2)。要求根据给定的K条关系,判断...

发表评论

访客

看不清,换一张

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