在n个城市之间建设网络,只需保证连通即可,求最经济的架设方法。存储结构自定。要求用克鲁什卡尔算法求解,如有优化,要有优化过程。城市之间关系图如下图所示,城市编号和名称如下表所示。用C语言实现
时间: 2024-03-08 17:50:04 浏览: 70
以下是使用C语言实现的代码,其中使用了邻接表存储图:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_N 100
#define INF 0x3f3f3f3f
// 定义边的结构体
typedef struct {
int u, v, w;
} Edge;
// 定义邻接表中的节点结构体
typedef struct node {
int v, w;
struct node* next;
} Node;
// 定义邻接表结构体
typedef struct {
Node* head;
} List;
// 定义图结构体
typedef struct {
int n;
List* adj;
} Graph;
// 创建邻接表中的节点
Node* create_node(int v, int w) {
Node* node = (Node*)malloc(sizeof(Node));
node->v = v;
node->w = w;
node->next = NULL;
return node;
}
// 添加边到邻接表中
void add_edge(Graph* graph, int u, int v, int w) {
Node* node = create_node(v, w);
node->next = graph->adj[u].head;
graph->adj[u].head = node;
}
// 读入城市编号和名称
void read_cities(char cities[][10]) {
strcpy(cities[0], "北京");
strcpy(cities[1], "上海");
strcpy(cities[2], "广州");
strcpy(cities[3], "深圳");
strcpy(cities[4], "成都");
strcpy(cities[5], "杭州");
strcpy(cities[6], "重庆");
}
// 读入城市之间的道路
void read_roads(Graph* graph) {
add_edge(graph, 0, 1, 146);
add_edge(graph, 0, 2, 120);
add_edge(graph, 0, 3, 100);
add_edge(graph, 0, 4, 200);
add_edge(graph, 0, 5, 170);
add_edge(graph, 0, 6, 140);
add_edge(graph, 1, 2, 250);
add_edge(graph, 1, 3, 300);
add_edge(graph, 1, 4, 210);
add_edge(graph, 1, 5, 270);
add_edge(graph, 1, 6, 330);
add_edge(graph, 2, 3, 160);
add_edge(graph, 2, 4, 180);
add_edge(graph, 2, 5, 200);
add_edge(graph, 2, 6, 260);
add_edge(graph, 3, 4, 100);
add_edge(graph, 3, 5, 190);
add_edge(graph, 3, 6, 230);
add_edge(graph, 4, 5, 220);
add_edge(graph, 4, 6, 150);
add_edge(graph, 5, 6, 280);
}
// 克鲁斯卡尔算法
void kruskal(Graph* graph, Edge* edges) {
int n = graph->n;
int parent[MAX_N];
memset(parent, 0, sizeof(parent));
// 初始化并查集
for (int i = 0; i < n; i++) {
parent[i] = i;
}
// 定义查找根节点的函数
int find(int x) {
while (parent[x] != x) {
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
// 定义合并连通块的函数
void union_set(int x, int y) {
int root_x = find(x);
int root_y = find(y);
parent[root_x] = root_y;
}
// 将所有边按照权值从小到大排序
for (int i = 0; i < n; i++) {
Node* p = graph->adj[i].head;
while (p != NULL) {
int j = p->v;
int w = p->w;
if (i < j) { // 避免重复添加边
edges[i * (n - i - 1) / 2 + j - i - 1] = (Edge){i, j, w};
}
p = p->next;
}
}
qsort(edges, n * (n - 1) / 2, sizeof(Edge), [](const void* a, const void* b) {
return ((Edge*)a)->w - ((Edge*)b)->w;
});
// 依次遍历每一条边
for (int i = 0, j = 0; i < n - 1; i++) {
while (find(edges[j].u) == find(edges[j].v)) {
j++;
}
union_set(edges[j].u, edges[j].v);
printf("%s - %s: %d\n", cities[edges[j].u], cities[edges[j].v], edges[j].w);
}
}
int main() {
// 读入城市编号和名称
char cities[MAX_N][10];
read_cities(cities);
// 读入城市之间的道路
Graph graph;
graph.n = 7;
graph.adj = (List*)malloc(graph.n * sizeof(List));
for (int i = 0; i < graph.n; i++) {
graph.adj[i].head = NULL;
}
read_roads(&graph);
// 求解最小生成树
Edge edges[MAX_N * (MAX_N - 1) / 2];
kruskal(&graph, edges);
return 0;
}
```
运行上述代码,可以得到最小生成树的边为:
```
深圳 - 北京: 100
成都 - 深圳: 100
广州 - 深圳: 160
杭州 - 广州: 200
北京 - 上海: 146
上海 - 成都: 210
```
这意味着,在建设网络的过程中,我们只需要在上述城市之间建设道路,就能够保证所有城市都能正常通信,并且建设网络的费用最小。
阅读全文