采用破圈法求一个带权连通图的最小生成树目的:深入了解图的复杂操作、图遍历算法和最小生成树的概念以及最小生成树的构造运算。内容:编写一个程序exp10cpp采用破圈法求一个带权连通图的最小生成树并测试。破圈法是带权连通图求最小生成树的另一种方法其思路是任意取一个圈去掉圈上图中权最大的一个边反复执行这个步骤直到图中没有圈为止。按以上要求对以下代码进行修改#include stdioh#include
修改后的代码如下:
#include <stdio.h> #include <stdlib.h> #include <stdbool.h>
#define MAX_VERTEX_NUM 100 // 最大顶点数 #define MAX_EDGE_NUM 1000 // 最大边数
// 边的结构体 typedef struct { int start; // 起点 int end; // 终点 int weight; // 权重 } Edge;
int parent[MAX_VERTEX_NUM]; // 存储每个节点的父节点 Edge edges[MAX_EDGE_NUM]; // 存储图的所有边 int edgeCount = 0; // 边的数量
// 查找节点的根节点 int find(int node) { while (parent[node] != -1) { node = parent[node]; } return node; }
// 合并两个节点所在的树 void unionSet(int root1, int root2) { parent[root1] = root2; }
// 按权重从大到小排序 void sortEdges() { for (int i = 0; i < edgeCount - 1; i++) { for (int j = 0; j < edgeCount - i - 1; j++) { if (edges[j].weight < edges[j + 1].weight) { Edge temp = edges[j]; edges[j] = edges[j + 1]; edges[j + 1] = temp; } } } }
// 判断边是否在圈中 bool isInCircle(int start, int end) { int root1 = find(start); int root2 = find(end); return root1 == root2; }
// 破圈法求最小生成树 void kruskal(int vertexCount) { for (int i = 0; i < vertexCount; i++) { parent[i] = -1; // 初始化每个节点的父节点为-1 }
sortEdges(); // 按边的权重从大到小排序
int edgeIndex = 0; // 当前处理的边的索引
int circleCount = vertexCount; // 圈的数量,初始值为顶点数
while (circleCount > 1 && edgeIndex < edgeCount) { // 直到图中没有圈或者处理完所有边
Edge edge = edges[edgeIndex++]; // 取出当前权重最大的边
if (!isInCircle(edge.start, edge.end)) { // 如果该边不在圈中
unionSet(find(edge.start), find(edge.end)); // 合并两个圈
circleCount--; // 圈的数量减1
printf("(%d, %d) weight=%d\n", edge.start, edge.end, edge.weight); // 输出加入最小生成树的边
}
}
}
int main() { int vertexCount, edgeNum; printf("请输入顶点和边的数目:\n"); scanf("%d%d", &vertexCount, &edgeNum);
printf("请输入每条边的起始顶点、结束顶点和权值:\n");
for (int i = 0; i < edgeNum; i++) {
scanf("%d%d%d", &edges[i].start, &edges[i].end, &edges[i].weight);
edgeCount++; // 边的数量加1
}
kruskal(vertexCount); // 使用破圈法求最小生成树
return 0;
原文地址: https://www.cveoy.top/t/topic/gjOq 著作权归作者所有。请勿转载和采集!