Open In App

Second Best Minimum Spanning Tree

Last Updated : 06 Jun, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Prerequisites Graph, Spanning tree, Disjoint Set (Union – Find).

A minimum spanning tree (MST) T, for a given graph G, spans over all vertices of a given graph and has minimum weight sum of all edges, out of all the possible spanning trees. 

Second best MST, T’, is a spanning tree with the second minimum weight sum of all edges, out of all spanning trees of graph G.

T and T’ differ by only one edge replacement. So, we should find an edge enew which is not in T and replace it with an edge in T (say eold) such that T’ = T union {enew} – {eold} is a spanning tree and weight difference of (enew – eold) is minimum (enew, eold are edges in the graph G).

Using Kruskal’s Algorithm

  • Use Kruskal’s algorithm to find MST T of graph G. Remove a single edge from it and replace it with another to obtain T’.
  • Sort the edges in O(ElogE) time (E-no.of edges) and find MST using Kruskal’s algorithm in O(E) time (No.of edges in MST = V-1 where V = no.of vertices in the graph G).
  • For each edge in MST, temporarily exclude it from the edge list (so that we cannot choose it).
  • Then, try to find MST in O(E) using the remaining edges. (no need to sort again)
  • Repeat the above for all edges in MST and take the best one. (with 2nd minimum weight sum). Thus, we obtained  T’ – second-best MST.
  • Overall Time Complexity – O(ElogE + E +VE) = O(VE)

Below is the implementation of the above approach:

C++




// C++ implementation to find the
// second best MST
 
#include <bits/stdc++.h>
using namespace std;
 
// used to implement union-find algorithm
int parent[100005];
 
// to keep track of edges in MST
vector<int> present;
 
// to keep track of number of edges
// in spanning trees other than the MST
int edg;
 
// a structure to represent a
// weighted edge in graph
struct edge {
    int src, dest, weight;
} edges[100005];
// array edges is of type edge.
 
// Compare two edges according
// to their weights.
// Used in sort() for sorting
// an array of edges
bool cmp(edge x, edge y)
{
    return x.weight < y.weight;
}
 
// initialising the array -
// each vertex is its own parent
// initially
void initialise(int n)
{
    // 1-indexed
    for (int i = 1; i <= n; i++)
        parent[i] = i;
}
 
// Implementing the union-find algorithm
int find(int x)
{
    if (parent[x] == x)
        return x;
    return parent[x] = find(parent[x]);
}
 
// Function to find the union
// for the Minimum spanning Tree
int union1(int i, int sum)
{
    int x, y;
    x = find(edges[i].src);
    y = find(edges[i].dest);
    if (x != y) {
 
        // parent of x = y (LCA) -
        // both are edge connected
        parent[x] = y;
 
        // keeping track of edges in MST
        present.push_back(i);
 
        // finding sum of weights
        // of edges in MST
        sum += edges[i].weight;
    }
    return sum;
}
 
// Function to find the second
// best minimum spanning Tree
int union2(int i, int sum)
{
    int x, y;
    x = find(edges[i].src);
    y = find(edges[i].dest);
    if (x != y) {
        // parent of x = y (LCA) -
        // both are edge connected
        parent[x] = y;
 
        // sum of weights of edges
        // in spanning tree
        sum += edges[i].weight;
        edg++;
    }
    return sum;
}
 
// Driver Code
int main()
{
    // V-> Number of vertices,
    // E-> Number of edges
    int V, E;
    V = 5;
    E = 8;
 
    // initialising the array to
    // be used for union-find
    initialise(V);
 
    // src, dest and weights can
    // also be taken from user as
    // input the following vectors
    // represent - source[0],
    // destination[0] are connected
    // by an edge with
    // weight[0]
 
    vector<int> source = { 1, 3, 2, 3,
                           2, 5, 1, 3 };
    vector<int> destination = { 3, 4, 4,
                                2, 5, 4, 2, 5 };
    vector<int> weights = { 75, 51, 19,
                            95, 42, 31, 9, 66 };
    for (int i = 0; i < E; i++) {
        edges[i].src = source[i];
        edges[i].dest = destination[i];
        edges[i].weight = weights[i];
    }
 
    // sorting the array of edges
    // based on edge weights
    sort(edges, edges + E, cmp);
 
    int sum = 0;
    for (int i = 0; i < E; i++) {
        sum = union1(i, sum);
    }
 
    // printing the cost of MST
    cout << "MST: " << sum << "\n";
 
    // initialising cost of second best MST
    int sec_best_mst = INT_MAX;
 
    // setting the sum to zero again.
    sum = 0;
    int j;
    for (j = 0; j < present.size(); j++) {
        initialise(V);
        edg = 0;
        for (int i = 0; i < E; i++) {
 
            // excluding one edge of
            // MST at a time
            // and forming spanning tree
            // with remaining
            // edges
            if (i == present[j])
                continue;
            sum = union2(i, sum);
        }
        // checking if number of edges = V-1 or not
        // since number of edges in a spanning tree of
        // graph with V vertices is (V-1)
        if (edg != V - 1) {
            sum = 0;
            continue;
        }
 
        // storing the minimum sum
        // in sec_best_mst
        if (sec_best_mst > sum)
            sec_best_mst = sum;
        sum = 0;
    }
 
    // printing the cost of second best MST
    cout << "Second Best MST: "
         << sec_best_mst << "\n";
    return 0;
}


Java




// Java implementation to find the
// second best MST
import java.util.*;
 
public class Main {
 
  // used to implement union-find algorithm
  static int[] parent = new int[100005];
 
  // to keep track of edges in MST
  static List<Integer> present = new ArrayList<>();
 
  // to keep track of number of edges
  // in spanning trees other than the MST
  static int edg;
 
 
  static class Edge implements Comparable<Edge> {
    int src, dest, weight;
 
    Edge(int src, int dest, int weight) {
      this.src = src;
      this.dest = dest;
      this.weight = weight;
    }
 
    @Override
    // array edges is of type edge.
 
    // Compare two edges according
    // to their weights.
    // Used in sort() for sorting
    // an array of edges
    public int compareTo(Edge other) {
      return this.weight - other.weight;
    }
  }
 
  // initialising the array -
  // each vertex is its own parent
  // initially
  static void initialise(int n) {
    // 1-indexed
    for (int i = 1; i <= n; i++)
      parent[i] = i;
  }
 
  // Implementing the union-find algorithm
  static int find(int x) {
    if (parent[x] == x)
      return x;
    return parent[x] = find(parent[x]);
  }
 
  // Function to find the union
  // for the Minimum spanning Tree
  static int union1(int i, int sum, Edge[] edges) {
    int x, y;
    x = find(edges[i].src);
    y = find(edges[i].dest);
    if (x != y) {
 
      // parent of x = y (LCA) -
      // both are edge connected
      parent[x] = y;
 
      // keeping track of edges in MST
      present.add(i);
      sum += edges[i].weight;
    }
    return sum;
  }
 
  // Function to find the second
  // best minimum spanning Tree
  static int union2(int i, int sum, Edge[] edges) {
    int x, y;
    x = find(edges[i].src);
    y = find(edges[i].dest);
    if (x != y) {
 
      // parent of x = y (LCA) -
      // both are edge connected
      parent[x] = y;
 
      // sum of weights of edges
      // in spanning tree
      sum += edges[i].weight;
      edg++;
    }
    return sum;
  }
 
  // Driver Code
  public static void main(String[] args) {
    // V-> Number of vertices,
    // E-> Number of edges
    int V = 5, E = 8;
 
    // initialising the array to
    // be used for union-find
    initialise(V);
 
    // src, dest and weights can
    // also be taken from user as
    // input the following vectors
    // represent - source[0],
    // destination[0] are connected
    // by an edge with
    // weight[0]
    int[] source = {1, 3, 2, 3, 2, 5, 1, 3};
    int[] destination = {3, 4, 4, 2, 5, 4, 2, 5};
    int[] weights = {75, 51, 19, 95, 42, 31, 9, 66};
    Edge[] edges = new Edge[E];
    for (int i = 0; i < E; i++) {
      edges[i] = new Edge(source[i], destination[i], weights[i]);
    }
 
 
    // sorting the array of edges
    // based on edge weights
    Arrays.sort(edges);
 
    int sum = 0;
    for (int i = 0; i < E; i++) {
      sum = union1(i, sum, edges);
    }
 
    // printing the cost of MST
    System.out.println("MST: " + sum);
 
    // initialising cost of second best MST
    int sec_best_mst = Integer.MAX_VALUE;
 
    // setting the sum to zero again.
    sum = 0;   
    int j;
    for (j = 0; j < present.size(); j++) {
      initialise(V);
      edg = 0;
      for (int i = 0; i < E; i++) {
 
        // excluding one edge of
        // MST at a time
        // and forming spanning tree
        // with remaining
        // edges
        if (i == present.get(j))
          continue;
        sum = union2(i, sum, edges);
      }
 
      // checking if number of edges = V-1 or not
      // since number of edges in a spanning tree of
      // graph with V vertices is (V-1)
      if (edg != V - 1) {
        sum = 0;
        continue;
      }
 
      // storing the minimum sum
      // in sec_best_mst
      if (sec_best_mst > sum)
        sec_best_mst = sum;
      sum = 0;
    }
 
    // printing the cost of second best MST
    System.out.println("Second Best MST: " + sec_best_mst);
  }
}
 
// This code is contributed by princekumaras


Python3




# Python implementation to find the
# second best MST
 
# used to implement union-find algorithm
parent = [i for i in range(100005)]
 
# to keep track of edges in MST
present = []
 
# to keep track of number of edges
# in spanning trees other than the MST
edg = 0
 
# a structure to represent a
# weighted edge in graph
class Edge:
    def __init__(self, src, dest, weight):
        self.src = src
        self.dest = dest
        self.weight = weight
 
# array edges is of type edge.
 
# Compare two edges according
# to their weights.
# Used in sorted() for sorting
# an array of edges
def cmp(x, y):
    return x.weight < y.weight
 
# initialising the array -
# each vertex is its own parent
# initially
def initialise(n):
    # 1-indexed
    for i in range(1, n+1):
        parent[i] = i
 
# Implementing the union-find algorithm
def find(x):
    if parent[x] == x:
        return x
    parent[x] = find(parent[x])
    return parent[x]
 
# Function to find the union
# for the Minimum spanning Tree
def union1(i, sum):
    global edg
    x = find(edges[i].src)
    y = find(edges[i].dest)
    if x != y:
        # parent of x = y (LCA) -
        # both are edge connected
        parent[x] = y
 
        # keeping track of edges in MST
        present.append(i)
 
        # finding sum of weights
        # of edges in MST
        sum += edges[i].weight
    return sum
 
# Function to find the second
# best minimum spanning Tree
 
 
def union2(i, sum):
    global edg
    x = find(edges[i].src)
    y = find(edges[i].dest)
    if x != y:
        # parent of x = y (LCA) -
        # both are edge connected
        parent[x] = y
 
        # sum of weights of edges
        # in spanning tree
        sum += edges[i].weight
        edg += 1
    return sum
 
# Driver Code
if __name__ == "__main__":
    # V-> Number of vertices,
    # E-> Number of edges
    V = 5
    E = 8
 
# initialising the array to
# be used for union-find
    initialise(V)
 
# src, dest and weights can
# also be taken from user as
# input the following vectors
# represent - source[0],
# destination[0] are connected
# by an edge with
# weight[0]
    source = [1, 3, 2, 3, 2, 5, 1, 3]
    destination = [3, 4, 4, 2, 5, 4, 2, 5]
    weights = [75, 51, 19, 95, 42, 31, 9, 66]
    # create a list of Edge objects
edges = [Edge(0, 0, 0) for _ in range(E)]
 
# fill in the values for each edge
for i in range(E):
    edges[i].src = source[i]
    edges[i].dest = destination[i]
    edges[i].weight = weights[i]
 
# sorting the array of edges
# based on edge weights
edges = sorted(edges, key=lambda x: x.weight)
sum = 0
for i in range(E):
    sum = union1(i, sum)
 
# printing the cost of MST
print("MST: ", sum)
 
# sorting the array of edges
# based on edge weights
edges = sorted(edges, key=lambda x: x.weight)
 
# initialising cost of second best MST
sec_best_mst = float('inf')
 
# setting the sum to zero again.
sum = 0
j = 0
while j < len(present):
    initialise(V)
    edg = 0
    i = 0
    while i < E:
        # excluding one edge of
        # MST at a time
        # and forming spanning tree
        # with remaining
        # edges
        if i == present[j]:
            i += 1
            continue
        sum = union2(i, sum)
        i += 1
    # checking if number of edges = V-1 or not
    # since number of edges in a spanning tree of
    # graph with V vertices is (V-1)
    if edg != V - 1:
        sum = 0
        j += 1
        continue
 
    # storing the minimum sum
    # in sec_best_mst
    if sec_best_mst > sum:
        sec_best_mst = sum
    sum = 0
    j += 1
 
# printing the cost of second best MST
print("Second Best MST: ", sec_best_mst)


C#




// C# code addition
using System;
using System.Collections.Generic;
using System.Linq;
 
class MainClass
{
 
  // used to implement union-find algorithm
  static int[] parent = new int[100005];
 
  // to keep track of edges in MST
  static List < int > present = new List < int > ();
 
  // to keep track of number of edges
  // in spanning trees other than the MST
  static int edg;
 
  class Edge: IComparable < Edge > {
    public int src,
    dest,
    weight;
 
    public Edge(int src, int dest, int weight) {
      this.src = src;
      this.dest = dest;
      this.weight = weight;
    }
 
    public int CompareTo(Edge other) {
      return this.weight - other.weight;
    }
  }
 
  // initialising the array -
  // each vertex is its own parent
  // initially
  static void initialise(int n) {
    // 1-indexed
    for (int i = 1; i <= n; i++)
      parent[i] = i;
  }
 
  // Implementing the union-find algorithm
  static int find(int x) {
    if (parent[x] == x)
      return x;
    return parent[x] = find(parent[x]);
  }
 
  // Function to find the union
  // for the Minimum spanning Tree
  static int union1(int i, int sum, Edge[] edges) {
    int x, y;
    x = find(edges[i].src);
    y = find(edges[i].dest);
    if (x != y) {
      // parent of x = y (LCA) -
      // both are edge connected
      parent[x] = y;
 
      // keeping track of edges in MST
      present.Add(i);
      sum += edges[i].weight;
    }
    return sum;
  }
 
  // Function to find the second
  // best minimum spanning Tree
  static int union2(int i, int sum, Edge[] edges) {
    int x, y;
    x = find(edges[i].src);
    y = find(edges[i].dest);
    if (x != y) {
      // parent of x = y (LCA) -
      // both are edge connected
      parent[x] = y;
 
      // sum of weights of edges
      // in spanning tree
      sum += edges[i].weight;
      edg++;
    }
    return sum;
  }
 
  // Driver Code
  public static void Main(string[] args) {
    int V = 5, E = 8;
 
    // initialising the array to
    // be used for union-find
    initialise(V);
 
    // src, dest and weights can
    // also be taken from user as
    // input the following vectors
    // represent - source[0],
    // destination[0] are connected
    // by an edge with
    // weight[0]
    int[] source = {1,3,2,3,2,5,1,3};
    int[] destination = {3,4,4,2,5,4,2,5};
    int[] weights = {75,51,19,95,42,31,9,66};
    Edge[] edges = new Edge[E];
    for (int i = 0; i < E; i++) {
      edges[i] = new Edge(source[i], destination[i], weights[i]);
    }
 
    // sorting the array of edges
    // based on edge weights
    Array.Sort(edges);
 
    int sum = 0;
    for (int i = 0; i < E; i++) {
      sum = union1(i, sum, edges);
    }
 
    // printing the cost of MST
    Console.WriteLine("MST: " + sum);
 
    // initialising cost of second best MST
    int sec_best_mst = int.MaxValue;
 
    // setting the sum to zero again.
    sum = 0;
    int j;
    for (j = 0; j < present.Count; j++) {
      initialise(V);
      edg = 0;
      for (int i = 0; i < E; i++) {
        // excluding one edge of
        // MST at a time
        // and forming spanning tree
        // with remaining
        // edges
        if (i == present[j])
          continue;
        sum = union2(i, sum, edges);
      }
 
      // checking if number of edges = V-1 or not
      // since number of edges in a spanning tree of
      // graph with V vertices is (V-1)
      if (edg != V - 1) {
        sum = 0;
        continue;
      }
 
      // storing the minimum sum
      // in sec_best_mst
      if (sec_best_mst > sum)
        sec_best_mst = sum;
      sum = 0;
    }
 
    // printing the cost of second best MST
    Console.WriteLine("Second Best MST: " + sec_best_mst);
  }
}
 
// The code is contributed by Nidhi goel.


Javascript




// JavaScript  implementation to find the
// second best MST
 
// used to implement union-find algorithm
let parent = [];
 
// to keep track of edges in MST
let present = [];
 
// to keep track of number of edges
// in spanning trees other than the MST
let edg;
 
// a structure to represent a
// weighted edge in graph
function Edge(src, dest, weight) {
  this.src = src;
  this.dest = dest;
  this.weight = weight;
}
 
// array edges is of type edge.
 
// Compare two edges according
// to their weights.
// Used in sort() for sorting
// an array of edges
 
function cmp(x, y) {
  return x.weight - y.weight;
}
 
// initialising the array -
// each vertex is its own parent
// initially
 
function initialise(n) {
  // 1-indexed
  for (let i = 1; i <= n; i++) {
    parent[i] = i;
  }
}
 
// Implementing the union-find algorithm
 
function find(x) {
  if (parent[x] === x) {
    return x;
  }
  return parent[x] = find(parent[x]);
}
 
 
 
// Function to find the union
// for the Minimum spanning Tree
function union1(i, sum) {
  let x = find(edges[i].src);
  let y = find(edges[i].dest);
  if (x !== y) {
     
     
        // parent of x = y (LCA) -
        // both are edge connected
    parent[x] = y;
    // keeping track of edges in MST
    present.push(i);
     
    // finding sum of weights
        // of edges in MST
    sum += edges[i].weight;
  }
  return sum;
}
 
// Function to find the second
// best minimum spanning Tree
function union2(i, sum) {
  let x = find(edges[i].src);
  let y = find(edges[i].dest);
  if (x !== y) {
     
    // parent of x = y (LCA) -
        // both are edge connected
    parent[x] = y;
     
    // sum of weights of edges
        // in spanning tree
    sum += edges[i].weight;
    edg++;
  }
  return sum;
}
 
// Driver Code
 
 
// V-> Number of vertices,
    // E-> Number of edges
let V = 5;
let E = 8;
 
    // initialising the array to
    // be used for union-find
initialise(V);
 
 
    // src, dest and weights can
    // also be taken from user as
    // input the following vectors
    // represent - source[0],
    // destination[0] are connected
    // by an edge with
    // weight[0]
 
let source = [1, 3, 2, 3, 2, 5, 1, 3];
let destination = [3, 4, 4, 2, 5, 4, 2, 5];
let weights = [75, 51, 19, 95, 42, 31, 9, 66];
 
let edges = new Array(E);
for (let i = 0; i < E; i++) {
  edges[i] = new Edge(source[i], destination[i], weights[i]);
}
 
 
    // sorting the array of edges
    // based on edge weights
edges.sort(cmp);
 
let sum = 0;
for (let i = 0; i < E; i++) {
  sum = union1(i, sum);
}
// printing the cost of MST
console.log("MST: " + sum);
 
// initialising cost of second best MST
let sec_best_mst = Infinity;
 
 // setting the sum to zero again.
sum = 0;
let j;
for (j = 0; j < present.length; j++) {
  initialise(V);
  edg = 0;
  for (let i = 0; i < E; i++) {
     
             // excluding one edge of
            // MST at a time
            // and forming spanning tree
            // with remaining
            // edges
    if (i === present[j]) {
      continue;
    }
    sum = union2(i, sum);
  }
   
        // checking if number of edges = V-1 or not
        // since number of edges in a spanning tree of
        // graph with V vertices is (V-1)
  if (edg !== V - 1) {
    sum = 0;
    continue;
  }
   
  // storing the minimum sum
        // in sec_best_mst
  if (sec_best_mst > sum) {
    sec_best_mst = sum;
  }
  sum = 0;
}
 
// printing the cost of second best MST
console.log("Second Best MST: " + sec_best_mst);


Output

MST: 110
Second Best MST: 121

Time Complexity – O(VE) where V – number of vertices in the input graph, E – number of edges in the input graph.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads