破圈法求最小生成樹c語言

以下是一個使用破圈法求最小生成樹的C語言程式示例:


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

#define MAX_VERTICES 100

// 定義圖的鄰接矩陣表示
int adjMatrix[MAX_VERTICES][MAX_VERTICES];

// 定義節點數和邊數
int n, m;

// 定義已訪問數組,用於記錄節點是否被訪問過
int visited[MAX_VERTICES];

// 定義節點權重的最小生成樹權值
int minWeight;

// 定義佇列用於廣度優先搜尋
struct Queue {
    int data[MAX_VERTICES];
    int front, rear;
} queue;

// 初始化佇列
void initQueue() {
    queue.front = queue.rear = 0;
}

// 入隊操作
void enqueue(struct Queue* queue, int v) {
    queue->data[queue->rear++] = v;
}

// 出隊操作
int dequeue(struct Queue* queue) {
    int v = queue->data[queue->front++];
    if (queue->front == queue->rear) {
        queue->rear = 0;
    } else if (queue->front == MAX_VERTICES) {
        queue->front = 1;
    }
    return v;
}

// 廣度優先搜尋算法,找到最小生成樹權值最小的邊並標記為已訪問
void BFS(int start) {
    initQueue(); // 初始化佇列
    visited[start] = 1; // 將起始節點標記為已訪問
    enqueue(&queue, start); // 將起始節點入隊
    while (!queue.rear) { // 當佇列非空時循環執行以下操作
        int cur = dequeue(&queue); // 取出隊首節點作為當前節點進行操作
        for (int i = 0; i < n; i++) { // 將當前節點的所有鄰居節點依次加入佇列並標記為已訪問(若未訪問過)
            if (adjMatrix[cur][i] && !visited[i]) { // 如果當前節點的鄰居節點存在且未被訪問過,則加入佇列並標記為已訪問
                visited[i] = 1; // 將鄰居節點標記為已訪問
                enqueue(&queue, i); // 將鄰居節點入隊(當前節點的最後一個鄰居除外)
            }
        }
    }
    minWeight = queue.front + 1; // 將起始節點和一條邊的權值加起來作為最小生成樹權值的最小值,並記錄下來以備後續使用(若存在多條邊)
}

// 輸出最小生成樹的所有邊及其權值(若存在多條邊)
void printMST(int start) {
    printf("Edge %d - %d\n", start, minWeight); // 輸出起始節點和一條邊的權值作為最小生成樹的一條邊(若存在多條邊)
    minWeight++; // 將最小生成樹權值的最小值加一,以備後續輸出剩餘邊的權值(若存在多條邊)
}

int main() {
    scanf("%d %d", &n, &m); // 輸入節點數和邊數(由於圖可能存在重複的邊,所以使用兩個變數分別表示)
    for (int i = 0; i < m; i++) { // 讀入每條邊的起點和終點以及權值(邊可能有重複出現的情況)
        int u, v, w; // 讀入起點、終點和權值,並記錄下來以備後續使用(若存在多條邊)
        scanf("%d %d %d", &u, &v, &w); // 讀入一條邊的起點、終點和權值(由於可能存在重複的邊,所以這裡讀入一個點)
        adjMatrix[u][v] = adjMatrix[v][u] = w; // 將相鄰的兩個點之間連上一條邊,並更新它們的權重為權值w(這裡為了簡化程式沒有使用指針來直接修改鄰接矩陣的值)
    }
    for (int i = 1; i <= n; i++) { // 將所有未被訪問過的節點標記為已訪問(由於可能存在重複的邊,所以這裡遍歷所有節點)
        visited[i] = 1; // 將所有未被訪問過的節點標記為已訪問(由於可能存在重複的邊,所以這裡只遍歷第一個未被訪問過的節點)