Created
December 26, 2021 14:23
-
-
Save HirbodBehnam/dcd5b06985dded94a6d802f8923d3443 to your computer and use it in GitHub Desktop.
Simple and inefficient prim algorithm implementation in C++
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <unordered_set> | |
#include <vector> | |
using namespace std; | |
class graph { | |
private: | |
typedef struct { | |
int to; | |
int weigh; | |
} edge; | |
vector<vector<edge>> neighbors; | |
// Get minimum element of a list which does not exist in excluded | |
static int get_min(const vector<int> &a, const unordered_set<int> &excluded) { | |
int min_dist = INT32_MAX, min_index; | |
for (int i = 0; i < a.size(); i++) | |
if (excluded.find(i) == excluded.end() && min_dist > a[i]) { | |
min_index = i; | |
min_dist = a[i]; | |
} | |
return min_index; | |
} | |
public: | |
// Create array with n vertices. Vertices are zero indexed | |
explicit graph(int vertices) { | |
neighbors = vector<vector<edge>>(vertices); | |
} | |
// Please note that the graph is undirected | |
void add_edge(int a, int b, int weigh) { | |
neighbors[a].push_back(edge{ | |
.to = b, | |
.weigh = weigh, | |
}); | |
neighbors[b].push_back(edge{ | |
.to = a, | |
.weigh = weigh, | |
}); | |
} | |
vector<pair<int, int>> prim() { | |
vector<pair<int, int>> result; | |
result.reserve(neighbors.size() - 1); | |
// Initialize the dist | |
vector<int> dist(neighbors.size()); | |
for (int &i: dist) // all set to infinity | |
i = INT32_MAX; | |
dist[0] = 0; // except the starting point | |
for (const auto &e: neighbors[0]) // and neighbors of starting point | |
dist[e.to] = e.weigh; | |
// Create a set for MST visited vertices | |
unordered_set<int> visited; | |
visited.reserve(neighbors.size()); | |
visited.insert(0); | |
// Also initialize the father of each vertex | |
vector<int> father(neighbors.size()); | |
for (const auto &e: neighbors[0]) // add neighbors of starting point | |
father[e.to] = 0; | |
// Start to look | |
while (visited.size() != neighbors.size()) { | |
int next = get_min(dist, visited); | |
visited.insert(next); | |
result.emplace_back(father[next], next); | |
for (const auto &n: neighbors[next]) { | |
if (visited.find(n.to) == visited.end() && n.weigh < dist[n.to]) { | |
dist[n.to] = n.weigh; | |
father[n.to] = next; | |
} | |
} | |
} | |
return result; | |
} | |
}; | |
int main() { | |
graph g(6); | |
g.add_edge(0, 1, 2); | |
g.add_edge(0, 2, 3); | |
g.add_edge(1, 3, 5); | |
g.add_edge(1, 4, 3); | |
g.add_edge(1, 2, 6); | |
g.add_edge(2, 4, 2); | |
g.add_edge(3, 5, 2); | |
g.add_edge(3, 4, 1); | |
g.add_edge(4, 5, 4); | |
auto result = g.prim(); | |
for (const auto &edges: result) | |
cout << edges.first << " " << edges.second << endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment