Reverse Delete Algorithm for Minimum Spanning Tree
Last Updated :
04 Aug, 2023
Reverse Delete algorithm is closely related to Kruskal’s algorithm. In Kruskal’s algorithm what we do is : Sort edges by increasing order of their weights. After sorting, we one by one pick edges in increasing order. We include current picked edge if by including this in spanning tree not form any cycle until there are V-1 edges in spanning tree, where V = number of vertices.
In Reverse Delete algorithm, we sort all edges in decreasing order of their weights. After sorting, we one by one pick edges in decreasing order. We include current picked edge if excluding current edge causes disconnection in current graph. The main idea is delete edge if its deletion does not lead to disconnection of graph.
The Algorithm :
- Sort all edges of graph in non-increasing order of edge weights.
- Initialize MST as original graph and remove extra edges using step 3.
- Pick highest weight edge from remaining edges and check if deleting the edge disconnects the graph or not.
If disconnects, then we don’t delete the edge.
Else we delete the edge and continue.
Illustration:
Let us understand with the following example:
If we delete highest weight edge of weight 14, graph doesn’t become disconnected, so we remove it.
Next we delete 11 as deleting it doesn’t disconnect the graph.
Next we delete 10 as deleting it doesn’t disconnect the graph.
Next is 9. We cannot delete 9 as deleting it causes disconnection.
We continue this way and following edges remain in final MST.
Edges in MST
(3, 4)
(0, 7)
(2, 3)
(2, 5)
(0, 1)
(5, 6)
(2, 8)
(6, 7)
Note : In case of same weight edges, we can pick any edge of the same weight edges.
Implementation:
C++
#include<bits/stdc++.h>
using namespace std;
typedef pair< int , int > iPair;
class Graph
{
int V;
list< int > *adj;
vector< pair< int , iPair> > edges;
void DFS( int v, bool visited[]);
public :
Graph( int V);
void addEdge( int u, int v, int w);
bool isConnected();
void reverseDeleteMST();
};
Graph::Graph( int V)
{
this ->V = V;
adj = new list< int >[V];
}
void Graph::addEdge( int u, int v, int w)
{
adj[u].push_back(v);
adj[v].push_back(u);
edges.push_back({w, {u, v}});
}
void Graph::DFS( int v, bool visited[])
{
visited[v] = true ;
list< int >::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
DFS(*i, visited);
}
bool Graph::isConnected()
{
bool visited[V];
memset (visited, false , sizeof (visited));
DFS(0, visited);
for ( int i=1; i<V; i++)
if (visited[i] == false )
return false ;
return true ;
}
void Graph::reverseDeleteMST()
{
sort(edges.begin(), edges.end());
int mst_wt = 0;
cout << "Edges in MST\n" ;
for ( int i=edges.size()-1; i>=0; i--)
{
int u = edges[i].second.first;
int v = edges[i].second.second;
adj[u]. remove (v);
adj[v]. remove (u);
if (isConnected() == false )
{
adj[u].push_back(v);
adj[v].push_back(u);
cout << "(" << u << ", " << v << ") \n" ;
mst_wt += edges[i].first;
}
}
cout << "Total weight of MST is " << mst_wt;
}
int main()
{
int V = 9;
Graph g(V);
g.addEdge(0, 1, 4);
g.addEdge(0, 7, 8);
g.addEdge(1, 2, 8);
g.addEdge(1, 7, 11);
g.addEdge(2, 3, 7);
g.addEdge(2, 8, 2);
g.addEdge(2, 5, 4);
g.addEdge(3, 4, 9);
g.addEdge(3, 5, 14);
g.addEdge(4, 5, 10);
g.addEdge(5, 6, 2);
g.addEdge(6, 7, 1);
g.addEdge(6, 8, 6);
g.addEdge(7, 8, 7);
g.reverseDeleteMST();
return 0;
}
|
Java
import java.util.*;
class Edge implements Comparable<Edge> {
int u, v, w;
Edge( int u, int v, int w)
{
this .u = u;
this .w = w;
this .v = v;
}
public int compareTo(Edge other)
{
return ( this .w - other.w);
}
}
public class GFG {
private int V;
private List<Integer>[] adj;
private List<Edge> edges;
@SuppressWarnings ({ "unchecked" , "deprecated" })
public GFG( int v)
{
V = v;
adj = new ArrayList[v];
for ( int i = 0 ; i < v; i++)
adj[i] = new ArrayList<Integer>();
edges = new ArrayList<Edge>();
}
public void AddEdge( int u, int v, int w)
{
adj[u].add(v);
adj[v].add(u);
edges.add( new Edge(u, v, w));
}
private void DFS( int v, boolean [] visited)
{
visited[v] = true ;
for ( int i : adj[v]) {
if (!visited[i])
DFS(i, visited);
}
}
private boolean IsConnected()
{
boolean [] visited = new boolean [V];
DFS( 0 , visited);
for ( int i = 1 ; i < V; i++) {
if (visited[i] == false )
return false ;
}
return true ;
}
public void ReverseDeleteMST()
{
Collections.sort(edges);
int mst_wt = 0 ;
System.out.println( "Edges in MST" );
for ( int i = edges.size() - 1 ; i >= 0 ; i--) {
int u = edges.get(i).u;
int v = edges.get(i).v;
adj[u].remove(adj[u].indexOf(v));
adj[v].remove(adj[v].indexOf(u));
if (IsConnected() == false ) {
adj[u].add(v);
adj[v].add(u);
System.out.println( "(" + u + ", " + v
+ ")" );
mst_wt += edges.get(i).w;
}
}
System.out.println( "Total weight of MST is "
+ mst_wt);
}
public static void main(String[] args)
{
int V = 9 ;
GFG g = new GFG(V);
g.AddEdge( 0 , 1 , 4 );
g.AddEdge( 0 , 7 , 8 );
g.AddEdge( 1 , 2 , 8 );
g.AddEdge( 1 , 7 , 11 );
g.AddEdge( 2 , 3 , 7 );
g.AddEdge( 2 , 8 , 2 );
g.AddEdge( 2 , 5 , 4 );
g.AddEdge( 3 , 4 , 9 );
g.AddEdge( 3 , 5 , 14 );
g.AddEdge( 4 , 5 , 10 );
g.AddEdge( 5 , 6 , 2 );
g.AddEdge( 6 , 7 , 1 );
g.AddEdge( 6 , 8 , 6 );
g.AddEdge( 7 , 8 , 7 );
g.ReverseDeleteMST();
}
}
|
Python3
class Graph:
def __init__( self , v):
self .v = v
self .adj = [ 0 ] * v
self .edges = []
for i in range (v):
self .adj[i] = []
def addEdge( self , u: int , v: int , w: int ):
self .adj[u].append(v)
self .adj[v].append(u)
self .edges.append((w, (u, v)))
def dfs( self , v: int , visited: list ):
visited[v] = True
for i in self .adj[v]:
if not visited[i]:
self .dfs(i, visited)
def connected( self ):
visited = [ False ] * self .v
self .dfs( 0 , visited)
for i in range ( 1 , self .v):
if not visited[i]:
return False
return True
def reverseDeleteMST( self ):
self .edges.sort(key = lambda a: a[ 0 ])
mst_wt = 0
print ( "Edges in MST" )
for i in range ( len ( self .edges) - 1 , - 1 , - 1 ):
u = self .edges[i][ 1 ][ 0 ]
v = self .edges[i][ 1 ][ 1 ]
self .adj[u].remove(v)
self .adj[v].remove(u)
if self .connected() = = False :
self .adj[u].append(v)
self .adj[v].append(u)
print ( "( %d, %d )" % (u, v))
mst_wt + = self .edges[i][ 0 ]
print ( "Total weight of MST is" , mst_wt)
if __name__ = = "__main__" :
V = 9
g = Graph(V)
g.addEdge( 0 , 1 , 4 )
g.addEdge( 0 , 7 , 8 )
g.addEdge( 1 , 2 , 8 )
g.addEdge( 1 , 7 , 11 )
g.addEdge( 2 , 3 , 7 )
g.addEdge( 2 , 8 , 2 )
g.addEdge( 2 , 5 , 4 )
g.addEdge( 3 , 4 , 9 )
g.addEdge( 3 , 5 , 14 )
g.addEdge( 4 , 5 , 10 )
g.addEdge( 5 , 6 , 2 )
g.addEdge( 6 , 7 , 1 )
g.addEdge( 6 , 8 , 6 )
g.addEdge( 7 , 8 , 7 )
g.reverseDeleteMST()
|
C#
using System;
using System.Collections.Generic;
public class Edge : IComparable<Edge> {
public int u, v, w;
public Edge( int u, int v, int w)
{
this .u = u;
this .v = v;
this .w = w;
}
public int CompareTo(Edge other)
{
return this .w.CompareTo(other.w);
}
}
public class Graph {
private int V;
private List< int >[] adj;
private List<Edge> edges;
public Graph( int v)
{
V = v;
adj = new List< int >[ v ];
for ( int i = 0; i < v; i++)
adj[i] = new List< int >();
edges = new List<Edge>();
}
public void AddEdge( int u, int v, int w)
{
adj[u].Add(v);
adj[v].Add(u);
edges.Add( new Edge(u, v, w));
}
private void DFS( int v, bool [] visited)
{
visited[v] = true ;
foreach ( int i in adj[v])
{
if (!visited[i])
DFS(i, visited);
}
}
private bool IsConnected()
{
bool [] visited = new bool [V];
DFS(0, visited);
for ( int i = 1; i < V; i++) {
if (visited[i] == false )
return false ;
}
return true ;
}
public void ReverseDeleteMST()
{
edges.Sort();
int mst_wt = 0;
Console.WriteLine( "Edges in MST" );
for ( int i = edges.Count - 1; i >= 0; i--) {
int u = edges[i].u;
int v = edges[i].v;
adj[u].Remove(v);
adj[v].Remove(u);
if (IsConnected() == false ) {
adj[u].Add(v);
adj[v].Add(u);
Console.WriteLine( "({0}, {1})" , u, v);
mst_wt += edges[i].w;
}
}
Console.WriteLine( "Total weight of MST is {0}" ,
mst_wt);
}
}
class GFG {
static void Main( string [] args)
{
int V = 9;
Graph g = new Graph(V);
g.AddEdge(0, 1, 4);
g.AddEdge(0, 7, 8);
g.AddEdge(1, 2, 8);
g.AddEdge(1, 7, 11);
g.AddEdge(2, 3, 7);
g.AddEdge(2, 8, 2);
g.AddEdge(2, 5, 4);
g.AddEdge(3, 4, 9);
g.AddEdge(3, 5, 14);
g.AddEdge(4, 5, 10);
g.AddEdge(5, 6, 2);
g.AddEdge(6, 7, 1);
g.AddEdge(6, 8, 6);
g.AddEdge(7, 8, 7);
g.ReverseDeleteMST();
}
}
|
Javascript
class Graph {
constructor(V) {
this .V = V;
this .adj = [];
this .edges = [];
for (let i = 0; i < V; i++) {
this .adj[i] = [];
}
}
addEdge(u, v, w) {
this .adj[u].push(v);
this .adj[v].push(u);
this .edges.push([w, [u, v]]);
}
DFS(v, visited) {
visited[v] = true ;
for (const i of this .adj[v]) {
if (!visited[i]) {
this .DFS(i, visited);
}
}
}
isConnected() {
const visited = [];
for (let i = 0; i < this .V; i++) {
visited[i] = false ;
}
this .DFS(0, visited);
for (let i = 1; i < this .V; i++) {
if (!visited[i]) {
return false ;
}
}
return true ;
}
reverseDeleteMST() {
this .edges.sort((a, b) => a[0] - b[0]);
let mstWt = 0;
console.log( "Edges in MST" );
for (let i = this .edges.length - 1; i >= 0; i--) {
const [u, v] = this .edges[i][1];
this .adj[u] = this .adj[u].filter(x => x !== v);
this .adj[v] = this .adj[v].filter(x => x !== u);
if (! this .isConnected()) {
this .adj[u].push(v);
this .adj[v].push(u);
console.log(`(${u}, ${v})`);
mstWt += this .edges[i][0];
}
}
console.log(`Total weight of MST is ${mstWt}`);
}
}
function main()
{
var V = 9;
var g = new Graph(V);
g.addEdge(0, 1, 4);
g.addEdge(0, 7, 8);
g.addEdge(1, 2, 8);
g.addEdge(1, 7, 11);
g.addEdge(2, 3, 7);
g.addEdge(2, 8, 2);
g.addEdge(2, 5, 4);
g.addEdge(3, 4, 9);
g.addEdge(3, 5, 14);
g.addEdge(4, 5, 10);
g.addEdge(5, 6, 2);
g.addEdge(6, 7, 1);
g.addEdge(6, 8, 6);
g.addEdge(7, 8, 7);
g.reverseDeleteMST();
}
main();
|
Output
Edges in MST
(3, 4)
(0, 7)
(2, 3)
(2, 5)
(0, 1)
(5, 6)
(2, 8)
(6, 7)
Total weight of MST is 37
Time complexity: O((E*(V+E)) + E log E) where E is the number of edges.
Space complexity: O(V+E) where V is the number of vertices and E is the number of edges. We are using adjacency list to store the graph, so we need space proportional to O(V+E).
Notes :
- The above implementation is a simple/naive implementation of Reverse Delete algorithm and can be optimized to O(E log V (log log V)3) [Source : Wiki]. But this optimized time complexity is still less than Prim and Kruskal Algorithms for MST.
- The above implementation modifies the original graph. We can create a copy of the graph if original graph must be retained.
Please Login to comment...