Dalam teori graf, mencari pokok rentang minimum (MST) bagi graf berwajaran bersambung adalah masalah biasa. MST ialah subset tepi graf yang menghubungkan semua bucu dan meminimumkan jumlah berat tepi. Algoritma yang cekap untuk menyelesaikan masalah ini ialah algoritma Boruvka.
struct Edge { int src, dest, weight; }; // Define the structure to represent a subset for union-find struct Subset { int parent, rank; };
Sekarang, mari kita gariskan langkah-langkah yang terlibat dalam mencari pokok rentang minimum dalam algoritma Boruvka −
Awalkan MST ke set kosong.
Buat subset untuk setiap bucu, dengan setiap subset mengandungi hanya satu bucu.
Ulang langkah berikut sehingga pokok rentang minimum (MST) mempunyai tepi V-1 (V ialah bilangan bucu dalam graf) −
Untuk setiap subset, cari tepi termurah yang menyambungkannya ke subset yang lain.
Tambahkan tepi yang dipilih pada pokok rentang minimum.
Lakukan operasi kesatuan pada subset tepi yang dipilih.
Keluarkan pokok rentang minimum.
Dalam algoritma Boruvka, terdapat pelbagai cara untuk mencari kelebihan termurah yang menghubungkan setiap subset. Berikut ialah dua kaedah biasa −
Untuk setiap subset, ulangi semua tepi dan cari tepi terkecil yang menyambungkannya ke subset yang lain.
Jejaki tepi yang dipilih dan lakukan operasi bersama.
#include <iostream> #include <vector> #include <algorithm> struct Edge { int src, dest, weight; }; // Define the structure to represent a subset for union-find struct Subset { int parent, rank; }; // Function to find the subset of an element using path compression int find(Subset subsets[], int i) { if (subsets[i].parent != i) subsets[i].parent = find(subsets, subsets[i].parent); return subsets[i].parent; } // Function to perform union of two subsets using union by rank void unionSets(Subset subsets[], int x, int y) { int xroot = find(subsets, x); int yroot = find(subsets, y); if (subsets[xroot].rank < subsets[yroot].rank) subsets[xroot].parent = yroot; else if (subsets[xroot].rank > subsets[yroot].rank) subsets[yroot].parent = xroot; else { subsets[yroot].parent = xroot; subsets[xroot].rank++; } } // Function to find the minimum spanning tree using Boruvka's algorithm void boruvkaMST(std::vector<Edge>& edges, int V) { std::vector<Edge> selectedEdges; // Stores the edges of the MST Subset* subsets = new Subset[V]; int* cheapest = new int[V]; // Initialize subsets and cheapest arrays for (int v = 0; v < V; v++) { subsets[v].parent = v; subsets[v].rank = 0; cheapest[v] = -1; } int numTrees = V; int MSTWeight = 0; // Keep combining components until all components are in one tree while (numTrees > 1) { for (int i = 0; i < edges.size(); i++) { int set1 = find(subsets, edges[i].src); int set2 = find(subsets, edges[i].dest); if (set1 != set2) { if (cheapest[set1] == -1 || edges[cheapest[set1]].weight > edges[i].weight) cheapest[set1] = i; if (cheapest[set2] == -1 || edges[cheapest[set2]].weight > edges[i].weight) cheapest[set2] = i; } } for (int v = 0; v < V; v++) { if (cheapest[v] != -1) { int set1 = find(subsets, edges[cheapest[v]].src); int set2 = find(subsets, edges[cheapest[v]].dest); if (set1 != set2) { selectedEdges.push_back(edges[cheapest[v]]); MSTWeight += edges[cheapest[v]].weight; unionSets(subsets, set1, set2); numTrees--; } cheapest[v] = -1; } } } // Output the MST weight and edges std::cout << "Minimum Spanning Tree Weight: " << MSTWeight << std::endl; std::cout << "Selected Edges:" << std::endl; for (const auto& edge : selectedEdges) { std::cout << edge.src << " -- " << edge.dest << " \tWeight: " << edge.weight << std::endl; } delete[] subsets; delete[] cheapest; } int main() { // Pre-defined input for testing purposes int V = 6; int E = 9; std::vector<Edge> edges = { {0, 1, 4}, {0, 2, 3}, {1, 2, 1}, {1, 3, 2}, {1, 4, 3}, {2, 3, 4}, {3, 4, 2}, {4, 5, 1}, {2, 5, 5} }; boruvkaMST(edges, V); return 0; }
Minimum Spanning Tree Weight: 9 Selected Edges: 0 -- 2 Weight: 3 1 -- 2 Weight: 1 1 -- 3 Weight: 2 4 -- 5 Weight: 1 3 -- 4 Weight: 2
Kami mula-mula mentakrifkan dua struktur - Tepi dan Subset. Tepi mewakili tepi dalam graf, termasuk sumber, destinasi dan berat tepi. Subset mewakili subset struktur data pertanyaan kesatuan, termasuk maklumat induk dan kedudukan.
Fungsi cari ialah fungsi pembantu yang menggunakan pemampatan laluan untuk mencari subset elemen. Ia secara rekursif mencari wakil (nod induk) subset yang mana elemen itu dimiliki dan memampatkan laluan untuk mengoptimumkan pertanyaan masa hadapan.
FungsiunionSets ialah satu lagi fungsi tambahan yang menggabungkan dua subset menggunakan penggabungan mengikut peringkat. Ia mencari wakil dua subset dan menggabungkannya berdasarkan pangkat untuk mengekalkan pokok yang seimbang.
Fungsi boruvkaMST mengambil sebagai input vektor tepi dan sebilangan bucu (V). Ia melaksanakan algoritma Boruvka untuk mencari MST.
Dalam fungsi boruvkaMST, kami mencipta vektor selectedEdges untuk menyimpan tepi MST.
Kami mencipta tatasusunan struktur Subset untuk mewakili subset dan memulakannya dengan nilai lalai.
Kami juga mencipta tatasusunan yang paling murah untuk menjejaki kelebihan termurah untuk setiap subset.
NumTrees pembolehubah dimulakan kepada bilangan bucu dan MSTWeight dimulakan kepada 0.
Algoritma berfungsi dengan menggabungkan komponen berulang kali sehingga semua komponen berada dalam pokok. Gelung utama berjalan sehingga numTrees menjadi 1.
Dalam setiap lelaran gelung utama, kami mengulangi semua tepi dan mencari tepi berwajaran minimum untuk setiap subset. Jika tepi menghubungkan dua subset berbeza, kami mengemas kini tatasusunan termurah dengan indeks tepi paling kurang wajaran.
Seterusnya, kami mengulangi semua subset Jika subset mempunyai kelebihan dengan berat minimum, kami menambahkannya pada vektorEdges yang dipilih, mengemas kini MSTWeight, melaksanakan operasi gabungan subset dan mengurangkan nilai numTrees.
Akhir sekali, kami mengeluarkan pemberat MST dan tepi terpilih.
Fungsi utama menggesa pengguna memasukkan bilangan bucu dan tepi. Ia kemudian mengambil input (sumber, sasaran, berat) untuk setiap tepi dan memanggil fungsi boruvkaMST dengan input.
Buat baris gilir keutamaan yang diisih mengikut berat untuk menyimpan tepi.
Untuk setiap subset, cari kelebihan berat minimum yang menyambungkannya ke subset lain daripada baris gilir keutamaan.
Jejaki tepi yang dipilih dan lakukan operasi bersama.
#include <iostream> #include <vector> #include <queue> #include <climits> using namespace std; // Edge structure representing a weighted edge in the graph struct Edge { int destination; int weight; Edge(int dest, int w) : destination(dest), weight(w) {} }; // Function to find the shortest path using Dijkstra's algorithm vector<int> dijkstra(const vector<vector<Edge>>& graph, int source) { int numVertices = graph.size(); vector<int> dist(numVertices, INT_MAX); vector<bool> visited(numVertices, false); dist[source] = 0; priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq; pq.push(make_pair(0, source)); while (!pq.empty()) { int u = pq.top().second; pq.pop(); if (visited[u]) { continue; } visited[u] = true; for (const Edge& edge : graph[u]) { int v = edge.destination; int weight = edge.weight; if (dist[u] + weight < dist[v]) { dist[v] = dist[u] + weight; pq.push(make_pair(dist[v], v)); } } } return dist; } int main() { int numVertices = 4; vector<vector<Edge>> graph(numVertices); // Adding edges to the graph graph[0].push_back(Edge(1, 2)); graph[0].push_back(Edge(2, 5)); graph[1].push_back(Edge(2, 1)); graph[1].push_back(Edge(3, 7)); graph[2].push_back(Edge(3, 3)); int source = 0; vector<int> shortestDistances = dijkstra(graph, source); cout << "Shortest distances from source vertex " << source << ":\n"; for (int i = 0; i < numVertices; i++) { cout << "Vertex " << i << ": " << shortestDistances[i] << endl; } return 0; }
Shortest distances from source vertex 0: Vertex 0: 0 Vertex 1: 2 Vertex 2: 3 Vertex 3: 6
Dalam pendekatan ini, kami menggunakan baris gilir keutamaan untuk mengoptimumkan proses mencari kelebihan berwajaran minimum untuk setiap subset. Di bawah ialah penjelasan terperinci tentang kod −
Struktur kod dan fungsi pembantu (seperti find dan unionSets) kekal sama seperti kaedah sebelumnya.
FungsiboruvkaMST diubah suai untuk menggunakan baris gilir keutamaan untuk mencari kelebihan wajaran minimum bagi setiap subset dengan cekap.
Daripada menggunakan tatasusunan termurah, kami kini mencipta baris gilir keutamaan (pq) tepi. Kami memulakannya dengan tepi graf.
Gelung utama berjalan sehingga numTrees menjadi 1, sama seperti kaedah sebelumnya.
Dalam setiap lelaran, kami mengekstrak kelebihan berat minimum (minEdge) daripada baris gilir keutamaan.
Kemudian kami menggunakan fungsi find untuk mencari subset yang menjadi milik sumber dan sasaran minEdge.
Jika subset berbeza, kami menambah minEdge pada vektorEdges yang dipilih, mengemas kini MSTWeight, melakukan gabungan subset dan mengurangkan numTrees.
Proses akan diteruskan sehingga semua komponen berada di dalam pokok.
Akhir sekali, kami mengeluarkan pemberat MST dan tepi terpilih.
Fungsi utama adalah sama seperti kaedah sebelumnya, kami telah menetapkan input untuk tujuan ujian.
Algoritma Boruvka menyediakan penyelesaian yang cekap untuk mencari pokok rentang minimum graf berwajaran. Pasukan kami meneroka dua laluan berbeza secara mendalam apabila melaksanakan algoritma dalam C++: pendekatan tradisional atau "naif". Satu lagi menggunakan baris gilir keutamaan. Bergantung pada keperluan khusus masalah yang diberikan di tangan. Setiap kaedah mempunyai kelebihan tertentu dan boleh dilaksanakan dengan sewajarnya. Dengan memahami dan melaksanakan algoritma Boruvka, anda boleh menyelesaikan masalah pokok rentang minimum dengan cekap dalam projek C++.
Atas ialah kandungan terperinci Algoritma Boruvka dalam C++ untuk pokok rentang minimum. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!