破圈法求最小生成樹c++

破圈法是一種求解最小生成樹(Minimum Spanning Tree,MST)的算法,其基本思想是在構建最小生成樹的過程中,每次從所有邊中選擇一條邊,這條邊的兩個頂點中的一個,去掉它所在邊上的所有點。重複這個過程直到只留下一個點,這就是最小生成樹。

下面是一個基於破圈法的 C++ 代碼實現:

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1e5 + 5;
vector<int> graph[MAXN]; // 鄰接表存儲圖
int parent[MAXN]; // 存儲樹的根節點
bool visited[MAXN]; // 標記節點是否被訪問過

void kruskal() {
    sort(graph[0].rbegin(), graph[0].rend()); // 先按照權重從小到大排序
    int n = 0; // 當前連通分量中的節點數
    for (int i = 0; i < MAXN; ++i) {
        if (!visited[i]) { // 如果節點未被訪問過
            n++; // 當前連通分量中的節點數加一
            parent[i] = n - 1; // 將當前節點加入樹的根節點中
            for (int j = 0; j < graph[i].size(); ++j) { // 將當前節點與它的鄰居節點都加入最小生成樹中
                int k = graph[i][j];
                if (!visited[k]) { // 如果鄰居節點未被訪問過
                    visited[k] = true; // 標記鄰居節點為已訪問
                    graph[n - 1].push_back(k); // 將鄰居節點加入當前連通分量中
                }
            }
        }
    }
}

int main() {
    int n, m; // n為節點數,m為邊數
    cin >> n >> m;
    for (int i = 0; i < m; ++i) { // 讀入邊的起點、終點和權重
        int u, v, w;
        cin >> u >> v >> w;
        graph[u].push_back(v); // 將邊加入鄰接表中
        graph[v].push_back(u); // 如果存在環,則需要添加這條邊
    }
    kruskal(); // 調用kruskal算法求解最小生成樹
    cout << parent[n - 1] << endl; // 輸出最小生成樹的根節點編號
    return 0;
}

這段代碼使用了鄰接表存儲圖,並使用了破圈法求解最小生成樹。在求解過程中,首先按照邊的權重從小到大排序,然後依次選擇邊加入最小生成樹中。在選擇邊時,需要判斷這條邊是否會形成環,如果會形成環,則跳過這條邊。最後輸出最小生成樹的根節點編號即可。