• Home
  • /
  • Blog
  • /
  • 2 Basic Algorithms to Find Minimum Spanning Trees

2 Basic Algorithms to Find Minimum Spanning Trees

Minimum Spanning Trees

This post is also available in: العربية (Arabic)

Consider a scenario of a cable TV company laying cable to a new locality. The constraint with it is that it can bury the cable only along certain paths, then there would be a graph representing which points are connected by those paths. 

Some of these paths might be more expensive, because they are longer, or require the cable to be buried deeper; these paths would be represented by edges with larger weights. 

A spanning tree for that graph would be a subset of those paths that has no cycles but still connects to every house. There might be several spanning trees possible. A minimum spanning tree would be one with the lowest total cost.

What is a Minimum Spanning Tree?

A minimum spanning tree basically is a tree. It is different from other trees in that it minimizes the total of the weights attached to the edges. Depending on what the graph looks like, there may be more than one minimum spanning tree.

In a graph where all the edges have the same weight, every tree is a minimum spanning tree. If all the edges have different weights (i.e., there are no two edges with the same weight), there is exactly one minimum spanning tree. On the other hand, if not all edges have different weights (some edges with different weights and some with equal weights), then there will be more than one minimum spanning tree.

Minimum Spanning Trees
Minimum Spanning Tree

What’s the Need to Find Minimum Spanning Trees?

A number of problems from the graph theory are called the minimum spanning tree problems. In graph theory, a tree is a way of connecting all the vertices together, so that there is exactly one path from any one vertex, to any other vertex of the tree.

If the graph represents a number of cities connected by roads, one could select a number of roads, so that each city can be reached from every other, but there is no more than one way to travel from one city to the other. 

A graph can have more than one spanning tree, just like there may be more than one way to select the roads between the cities.

Most of the time, graphs are weighted; each connection between two cities has a weight. It can be the distance, cost of transportation, or time to travel.

Algorithms to find Minimum Spanning Tree

There are two famous algorithms for finding the Minimum Spanning Tree.

Kruksal’s Algorithm

It builds the spanning tree by adding edges one by one into a growing spanning tree. Kruksal’s algorithm follows a greedy approach as in each iteration it finds an edge that has the least weight and adds it to the growing spanning tree.

Steps in Kruksal’s algorithm

  • Sort the graph edges with respect to their weights.
  • Start adding edges to the Minimum Spanning Tree from the edge with the smallest weight until the edge of the largest weight.
  • Only add edges that don’t form a cycle, edges that connect only disconnected components.

In Kruskal’s algorithm, at each iteration, we will select the edge with the lowest weight. So, we will start with the lowest weighted edge first i.e., the edges with weight 1.

After that, we will select the second-lowest weighted edge i.e., edge with weight 2. Notice these two edges are totally disjoint.

Now, the next edge will be the third-lowest weighted edge i.e., edge with weight 3, which connects the two disjoint pieces of the graph.

Now, we are not allowed to pick the edge with weight 4, which will create a cycle and we can’t have any cycles. So we will select the fifth-lowest weighted edge i.e., edge with weight 5. Now the other two edges will create cycles so we will ignore them. In the end, we end up with a minimum spanning tree with total cost 11 ( = 1 + 2 + 3 + 5).

Minimum Spanning Trees
Kruksal’s algorithm

C++ Program to Implement Kruksal’s Algorithm

#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>

using namespace std;
const int MAX = 1e4 + 5;
int id[MAX], nodes, edges;
pair <long long, pair<int, int> > p[MAX];

void initialize()
{
    for(int i = 0;i < MAX;++i)
        id[i] = i;
}

int root(int x)
{
    while(id[x] != x)
    {
        id[x] = id[id[x]];
        x = id[x];
    }
    return x;
}

void union1(int x, int y)
{
    int p = root(x);
    int q = root(y);
    id[p] = id[q];
}

long long kruskal(pair<long long, pair<int, int> > p[])
{
    int x, y;
    long long cost, minimumCost = 0;
    for(int i = 0;i < edges;++i)
    {
        // Selecting edges one by one in increasing order from the beginning
        x = p[i].second.first;
        y = p[i].second.second;
        cost = p[i].first;
        // Check if the selected edge is creating a cycle or not
        if(root(x) != root(y))
        {
            minimumCost += cost;
            union1(x, y);
        }    
    }
    return minimumCost;
}

int main()
{
    int x, y;
    long long weight, cost, minimumCost;
    initialize();
    cin >> nodes >> edges;
    for(int i = 0;i < edges;++i)
    {
        cin >> x >> y >> weight;
        p[i] = make_pair(weight, make_pair(x, y));
    }
    // Sort the edges in the ascending order
    sort(p, p + edges);
    minimumCost = kruskal(p);
    cout << minimumCost << endl;
    return 0;
}

Prim’s Algorithm

Prim’s Algorithm also use Greedy approach to find the minimum spanning tree. In Prim’s Algorithm we grow the spanning tree from a starting position. Unlike an edge in Kruskal’s, we add vertex to the growing spanning tree in Prim’s.

Steps in Prim’s algorithm

  • Maintain two disjoint sets of vertices. One containing vertices that are in the growing spanning tree and other that are not in the growing spanning tree.
  • Select the cheapest vertex that is connected to the growing spanning tree and is not in the growing spanning tree and add it into the growing spanning tree. This can be done using Priority Queues. Insert the vertices, that are connected to growing spanning tree, into the Priority Queue.
  • Check for cycles. To do that, mark the nodes which have been already selected and insert only those nodes in the Priority Queue that are not marked.

In Prim’s Algorithm, we will start with an arbitrary node (it doesn’t matter which one) and mark it. In each iteration we will mark a new vertex that is adjacent to the one that we have already marked.

As a greedy algorithm, Prim’s algorithm will select the cheapest edge and mark the vertex. So we will simply choose the edge with weight 1. In the next iteration, we have three options, edges with weight 2, 3, and 4. So, we will select the edge with weight 2 and mark the vertex. Now again we have three options, edges with weight 3, 4, and 5. But we can’t choose an edge with weight 3 as it is creating a cycle. So we will select the edge with weight 4 and we end up with the minimum spanning tree of total cost 7 ( = 1 + 2 +4).

Minimum Spanning Trees
Prim’s algorithm

C++ Program to Implement Prim’s Algorithm

#include <iostream>
#include <vector>
#include <queue>
#include <functional>
#include <utility>

using namespace std;
const int MAX = 1e4 + 5;
typedef pair<long long, int> PII;
bool marked[MAX];
vector <PII> adj[MAX];

long long prim(int x)
{
    priority_queue<PII, vector<PII>, greater<PII> > Q;
    int y;
    long long minimumCost = 0;
    PII p;
    Q.push(make_pair(0, x));
    while(!Q.empty())
    {
        // Select the edge with minimum weight
        p = Q.top();
        Q.pop();
        x = p.second;
        // Checking for cycle
        if(marked[x] == true)
            continue;
        minimumCost += p.first;
        marked[x] = true;
        for(int i = 0;i < adj[x].size();++i)
        {
            y = adj[x][i].second;
            if(marked[y] == false)
                Q.push(adj[x][i]);
        }
    }
    return minimumCost;
}

int main()
{
    int nodes, edges, x, y;
    long long weight, minimumCost;
    cin >> nodes >> edges;
    for(int i = 0;i < edges;++i)
    {
        cin >> x >> y >> weight;
        adj[x].push_back(make_pair(weight, y));
        adj[y].push_back(make_pair(weight, x));
    }
    // Selecting 1 as the starting node
    minimumCost = prim(1);
    cout << minimumCost << endl;
    return 0;
}

Applications of Minimum Spanning Trees

  • Minimum spanning trees are used for network designs (i.e., telephone or cable networks). They are also used to find approximate solutions for complex mathematical problems like the ‘Traveling Salesman Problem”. 
  • Cluster Analysis
  • Real-time face tracking and verification (i.e., locating human faces in a video stream)
  • Protocols in computer science to avoid network cycles
  • Entropy-based image registration
  • Dithering (adding white noise to a digital recording in order to reduce distortion)
  • Handwriting recognition
  • Image segmentation

Image Credit: Background vector created by vector_corp – www.freepik.com

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
>