Skip to content

Instantly share code, notes, and snippets.

@HirbodBehnam
Created December 26, 2021 14:23
Show Gist options
  • Save HirbodBehnam/dcd5b06985dded94a6d802f8923d3443 to your computer and use it in GitHub Desktop.
Save HirbodBehnam/dcd5b06985dded94a6d802f8923d3443 to your computer and use it in GitHub Desktop.
Simple and inefficient prim algorithm implementation in C++
#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