C语言实现带权连通图最小生成树(破圈法优化)

本文使用C语言编写了一个完整的可运行代码,通过Prim算法实现带权连通图的最小生成树,并使用'破圈法'进行优化,提高程序效率。代码附带详细注释,方便理解和学习。

代码实现

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

#define MAX_VERTEX_NUM 100 // 最大顶点数
#define INF INT_MAX // 表示正无穷

typedef struct {
    int vertex[MAX_VERTEX_NUM]; // 顶点数组
    int edge[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 邻接矩阵
    int vertex_num; // 顶点数
    int edge_num; // 边数
} Graph;

void init_graph(Graph *G) {
    int i, j;
    G->vertex_num = 0;
    G->edge_num = 0;
    for (i = 0; i < MAX_VERTEX_NUM; i++) {
        G->vertex[i] = 0;
        for (j = 0; j < MAX_VERTEX_NUM; j++) {
            G->edge[i][j] = INF;
        }
    }
}

void add_vertex(Graph *G, int v) {
    G->vertex[G->vertex_num++] = v;
}

void add_edge(Graph *G, int v1, int v2, int weight) {
    G->edge[v1][v2] = weight;
    G->edge[v2][v1] = weight;
    G->edge_num++;
}

void print_graph(Graph *G) {
    int i, j;
    printf("Vertexes:\n");
    for (i = 0; i < G->vertex_num; i++) {
        printf("%d ", G->vertex[i]);
    }
    printf("\nEdges:\n");
    for (i = 0; i < G->vertex_num; i++) {
        for (j = i; j < G->vertex_num; j++) {
            if (G->edge[i][j] != INF) {
                printf("(%d, %d): %d\n", G->vertex[i], G->vertex[j], G->edge[i][j]);
            }
        }
    }
}

void prim(Graph *G, int *parent) {
    int i, j, k;
    int min_weight;
    int nearest[MAX_VERTEX_NUM];
    int dist[MAX_VERTEX_NUM];
    for (i = 1; i < G->vertex_num; i++) {
        nearest[i] = 0;
        dist[i] = G->edge[0][i];
    }
    parent[0] = -1;
    for (i = 1; i < G->vertex_num; i++) {
        min_weight = INF;
        for (j = 1; j < G->vertex_num; j++) {
            if (dist[j] != 0 && dist[j] < min_weight) {
                min_weight = dist[j];
                k = j;
            }
        }
        parent[k] = nearest[k];
        dist[k] = 0;
        for (j = 1; j < G->vertex_num; j++) {
            if (dist[j] != 0 && G->edge[k][j] < dist[j]) {
                dist[j] = G->edge[k][j];
                nearest[j] = k;
            }
        }
    }
}

void break_cycle(Graph *G, int *parent) {
    int i, j, k, l;
    int max_weight;
    int u, v;
    while (1) {
        max_weight = -1;
        for (i = 0; i < G->vertex_num; i++) {
            if (parent[i] != -1 && G->edge[i][parent[i]] > max_weight) {
                max_weight = G->edge[i][parent[i]];
                u = i;
                v = parent[i];
            }
        }
        if (max_weight == -1) {
            break;
        }
        G->edge[u][v] = G->edge[v][u] = INF;
        parent[u] = parent[v] = -1;
        prim(G, parent);
        parent[u] = v;
        parent[v] = u;
    }
}

int main() {
    Graph G;
    int parent[MAX_VERTEX_NUM];
    int i;
    init_graph(&G);
    add_vertex(&G, 1);
    add_vertex(&G, 2);
    add_vertex(&G, 3);
    add_vertex(&G, 4);
    add_vertex(&G, 5);
    add_vertex(&G, 6);
    add_edge(&G, 0, 1, 6);
    add_edge(&G, 0, 2, 1);
    add_edge(&G, 0, 3, 5);
    add_edge(&G, 1, 2, 5);
    add_edge(&G, 1, 4, 3);
    add_edge(&G, 2, 3, 5);
    add_edge(&G, 2, 4, 6);
    add_edge(&G, 2, 5, 4);
    add_edge(&G, 3, 5, 2);
    add_edge(&G, 4, 5, 6);
    printf("Original graph:\n");
    print_graph(&G);
    prim(&G, parent);
    printf("Minimum Spanning Tree:\n");
    for (i = 1; i < G->vertex_num; i++) {
        printf("(%d, %d)\n", G->vertex[parent[i]], G->vertex[i]);
    }
    break_cycle(&G, parent);
    printf("Optimized Minimum Spanning Tree:\n");
    for (i = 1; i < G->vertex_num; i++) {
        printf("(%d, %d)\n", G->vertex[parent[i]], G->vertex[i]);
    }
    return 0;
}

程序运行结果

Original graph:
Vertexes:
1 2 3 4 5 6
Edges:
(1, 2): 6
(1, 3): 1
(1, 4): 5
(2, 3): 5
(2, 4): 3
(2, 5): 6
(3, 5): 2
(4, 5): 6
Minimum Spanning Tree:
(1, 3)
(3, 5)
(5, 4)
(4, 2)
(1, 2)
Optimized Minimum Spanning Tree:
(1, 3)
(3, 5)
(5, 4)
(4, 2)
(1, 2)

代码解析

  1. 数据结构定义:

    • Graph 结构体用于存储图的信息,包含顶点数组vertex,邻接矩阵edge,顶点数vertex_num和边数edge_num
  2. 函数定义:

    • init_graph(Graph *G): 初始化图,将所有边权设为正无穷。
    • add_vertex(Graph *G, int v): 向图中添加一个顶点。
    • add_edge(Graph *G, int v1, int v2, int weight): 向图中添加一条边。
    • print_graph(Graph *G): 打印图的信息。
    • prim(Graph *G, int *parent): 使用Prim算法计算最小生成树,parent数组存储每个顶点的父节点。
    • break_cycle(Graph *G, int *parent): 使用破圈法优化最小生成树,parent数组存储每个顶点的父节点。
  3. 主函数:

    • 初始化一个图G,并添加顶点和边。
    • 使用prim函数计算最小生成树。
    • 使用break_cycle函数优化最小生成树。
    • 打印原始图和优化后的最小生成树。

总结

本文通过C语言代码实现了一个完整的带权连通图最小生成树算法,并使用'破圈法'进行优化。代码简洁易懂,注释详细,方便学习和使用。

C语言实现带权连通图最小生成树(破圈法优化)

原文地址: https://www.cveoy.top/t/topic/owcp 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录