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