题解 | #最小生成树#

最小生成树

https://www.nowcoder.com/practice/735a34ff4672498b95660f43b7fcd628

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <limits.h>

// 定义边的结构体
struct Edge {
    int src, dest, weight;
};

// 定义图的结构体
struct Graph {
    int V, E;
    struct Edge* edges; // 保存图的所有边
};

// 创建图的函数
struct Graph* createGraph(int V, int E) {
    struct Graph* graph = (struct Graph*)malloc(sizeof(struct Graph)); // 分配图的内存空间
    graph->V = V; // 图的顶点数
    graph->E = E; // 图的边数
    graph->edges = (struct Edge*)malloc(E * sizeof(struct Edge)); // 分配边数组的内存空间
    return graph;
}

// 寻找节点的根节点(用于判断两个节点是否属于同一个集合)
int findParent(int parent[], int i) {
    if (parent[i] == -1)
        return i;
    return findParent(parent, parent[i]);
}

// 合并两个集合
void unionSet(int parent[], int x, int y) {
    int xSet = findParent(parent, x);
    int ySet = findParent(parent, y);
    parent[xSet] = ySet;
}

// 用于 qsort 的比较函数,按照边的权重升序排序
int compareEdges(const void* a, const void* b) {
    struct Edge* edgeA = (struct Edge*)a;
    struct Edge* edgeB = (struct Edge*)b;
    return edgeA->weight - edgeB->weight;
}

// 主函数,实现 Kruskal 算法找到最小生成树的总权重
int miniSpanningTree(int n, int m, int** cost, int costRowLen, int* costColLen ) {
    // 创建图
    struct Graph* graph = createGraph(n, m * 2);

    // 将输入转换为图的边集合
    for (int i = 0; i < m; ++i) {
        graph->edges[i].src = cost[i][0] - 1;
        graph->edges[i].dest = cost[i][1] - 1;
        graph->edges[i].weight = cost[i][2];

        graph->edges[i + m].src = cost[i][1] - 1;
        graph->edges[i + m].dest = cost[i][0] - 1;
        graph->edges[i + m].weight = cost[i][2];
    }

    int V = graph->V; // 顶点数
    int E = graph->E; // 边数

    qsort(graph->edges, E, sizeof(struct Edge), compareEdges); // 对边按权重排序

    int parent[V]; // 用于记录节点的父节点
    memset(parent, -1, sizeof(parent)); // 初始化节点的父节点为 -1,表示各自是独立的集合

    int totalCost = 0; // 记录最小生成树的总权重
    int e = 0; // 边的计数器
    int edgesConsidered = 0; // 已考虑的边的计数器

    // 进行 Kruskal 算法,逐个考虑边
    while (edgesConsidered < V - 1) {
        struct Edge nextEdge = graph->edges[e++];
        int x = findParent(parent, nextEdge.src);
        int y = findParent(parent, nextEdge.dest);

        // 判断两个节点是否属于同一个集合,如果不是,则将这两个节点合并到一个集合中,并将边的权重添加到总权重中
        if (x != y) {
            totalCost += nextEdge.weight;
            unionSet(parent, x, y);
            edgesConsidered++;
        }
    }

    free(graph->edges); // 释放边数组内存
    free(graph); // 释放图的内存

    // 如果最终形成的最小生成树的边数不是 V-1,则说明图不是完全连接的,返回 -1 表示无法构建最小生成树
    if (edgesConsidered != V - 1) {
        return -1; // 图不是完全连接的
    }

    return totalCost; // 返回最小生成树的
}

全部评论

相关推荐

05-28 23:26
河南大学 Java
双非本,刚学完Redis,项目只有外卖和点评,八股没准备,算法只有lqb省一,感觉敲的项目也是一言难尽没怎么吸收。怎么你们都有实习了
大牛之途:27急个锤子,你投日常实习最好的时间就是9,10月份,那时候暑期实习都结束了,正是缺人的时候。这份日常又能给你的暑期实习增加竞争力,暑期找的好了秋招也不怕了,都是环环相扣的
点赞 评论 收藏
分享
关于我大学本科四年,想了很多,但还是不知道该怎么动笔&nbsp;“大学四年,是我从懵懂少年走向职场青年的转折期。这一路跌跌撞撞,有迷茫,有遗憾,也有成长和决心。”&nbsp;大一刚进来时仍然有高中那股学习劲,经常一个人去图书馆学高等数学,但后面劲头一过便开始在宿舍开启躺平生活(现在想想那段时间真的很爽,无忧无虑)。由于大一担任班干部,所以经常要跟其他班的班干部交流,在此期间认识了隔壁班的一位女生,短发而很可爱,因为很多团建还有比赛都是我们两班一起参加的,而且我和她都是负责人,所以交集很多,后面慢慢地彼此对产生了好感,所以在大一刚开学的2个月后,我们在一起了,彼此之前都是初恋。但当时我真的是太太太直男了,对感情的想...
真烦好烦真烦:骗哥们可以,别把你自己也骗到了就行。哥们被你骗了真无所谓的,打个哈哈就过了。但希望你打完这段话后擦一下眼角,别让眼泪掉在手机屏幕上了就行。你说的这些话,哥们信一下也是没什么的。还能让你有个心里安慰,但这种话说出来骗骗兄弟就差不多得了,哥们信你一下也不会少块肉,但是你别搞得自己也当真了就行。哥们被你骗一下是真无所谓的,兄弟笑笑也就过去了。真不是哥们想要破你防,你擦擦眼泪好好想想,除了兄弟谁还会信你这些话?
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
05-01 13:13
ecece:这么明目张胆虚报就业率啊
点赞 评论 收藏
分享
04-19 11:59
门头沟学院 Java
卷不动辣24314:挂,看来不该投这个部门的
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务