Find the weight of the minimum spanning tree (original) (raw)

Last Updated : 11 Jul, 2025

Given a connected undirected weighted graph with **N nodes and **M edges. The task is to perform given queries and find the weight of the minimum spanning tree. Queries are of three types:

  1. **query(1) -> Find the weight of the minimum spanning tree.
  2. **query(2, x, y) -> Change the weight of the edge between the nodes **x and **y to **0.
  3. **query(3, x, y) -> Restore the weight of the edge between the nodes **x and **y to its **original weight.

**Examples:

**Input:

query(2, 1, 2),
query(1),
query(3, 1, 2),
query(1)
**Output:
2
3
**Input:

query(1),
query(2, 3, 4),
query(1)
**Output :
4
2

**Approach: Let’s first compute MST of the initial graph before performing any queries and let T be this MST. The crucial observation is that at any point while handling the queries, the weight of the MST of the current graph can be computed by running Kruskal’s algorithm on edges with zero weight at this point and edges of T. So, keep edges with weight zero in a data structure and after query of type 2 and type 3 compute weight of minimum spanning tree.
Below is the implementation of the above approach:

C++ `

// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; #define N 2005

// To store vertices, edges // and the required answer int n, m, ans;

// To store parent and rank int par[N], Rank[N];

// To store edges and the edges in MST vector<pair<int, pair<int, int> > > edges, mst;

// To store the edges with weight zero queue<pair<int, int> > zeros;

// Function for initialize void initialize() { for (int i = 0; i <= n; i++) { par[i] = i; Rank[i] = 0; } }

// Function to add edges void Add_edge(int u, int v, int weight) { edges.push_back({ weight, { u, v } }); }

// Utility function to find set of an element i // (uses path compression technique) int find(int x) { if (par[x] != x) par[x] = find(par[x]);

return par[x];

}

// Function that performs union of two sets x and y // (uses union by rank) void Union(int x, int y) { int xroot = find(x); int yroot = find(y);

if (Rank[xroot] < Rank[yroot])
    par[xroot] = yroot;
else if (Rank[xroot] > Rank[yroot])
    par[yroot] = xroot;
else {
    par[yroot] = xroot;
    Rank[xroot]++;
}

}

// Function to compute minimum spanning tree void compute_MST() { // Sort edges in increasing order of weight sort(edges.begin(), edges.end());

// Go through all the edges
for (int i = 0; i < m; i++) {
    int u = find(edges[i].second.first);
    int v = find(edges[i].second.second);

    if (u == v)
        continue;

    // Build minimum spanning tree
    // and store minimum cost
    mst.push_back(edges[i]);
    ans += edges[i].first;
    Union(u, v);
}

}

// Function to find the cost of minimum // spanning tree void Modified_Kruskal(pair<int, int> x) { initialize();

// Make answer zero
ans = 0;
int sz = zeros.size();

// Keep the edges which only have zero weights
// and remove all the other edges
for (int i = 0; i < sz; i++) {
    pair<int, int> Front = zeros.front();
    zeros.pop();

    if (Front.first == x.first
        and Front.second == x.second)
        continue;

    // Make union between the vertices of
    // edges which have weight zero and keep
    // them in queue
    Union(Front.first, Front.second);
    zeros.push(Front);
}

// Find the cost of the minimum spanning tree
for (int i = 0; i < mst.size(); i++) {
    int u = find(mst[i].second.first);
    int v = find(mst[i].second.second);

    if (u == v)
        continue;

    ans += mst[i].first;
    Union(u, v);
}

}

// Function to handle different queries void query(int type, int u = 0, int v = 0) {

// Update edge weight to 0
if (type == 2) {
    // push edge in zeros
    zeros.push({ u, v });
    Modified_Kruskal({ -1, -1 });
}

// Restore edge weight to original value
else if (type == 3) {
    // push edge in zeros
    zeros.push({ u, v });
    Modified_Kruskal({ u, v });
}
else
    cout << ans << endl;

}

// Driver code int main() {

// Number of nodes and edges
n = 4, m = 4;
initialize();

// Add edges
Add_edge(1, 2, 1);
Add_edge(2, 3, 1);
Add_edge(3, 4, 1);
Add_edge(4, 1, 1);

// Build the minimum spanning tree
compute_MST();

// Execute queries
query(2, 1, 2);
query(1);
query(3, 1, 2);
query(1);

return 0;

}

Java

import java.util.*;

class Main { static final int N = 2005; static int n, m, ans; static int[] par, Rank; static List edges, mst; static Queue zeros;

// Pair class to represent edges and vertices
static class Pair {
    int first, second;

    Pair(int first, int second) {
        this.first = first;
        this.second = second;
    }
}

// Function to initialize data structures
static void initialize() {
    par = new int[N];
    Rank = new int[N];
    for (int i = 0; i <= n; i++) {
        par[i] = i;
        Rank[i] = 0;
    }
}

// Function to add edges
static void Add_edge(int u, int v, int weight) {
    edges.add(new Pair(weight, (u << 10) | v));
}

// Utility function to find set of an element i (uses path compression technique)
static int find(int x) {
    if (par[x] != x)
        par[x] = find(par[x]);
    return par[x];
}

// Function that performs union of two sets x and y (uses union by rank)
static void Union(int x, int y) {
    int xroot = find(x);
    int yroot = find(y);
    if (Rank[xroot] < Rank[yroot])
        par[xroot] = yroot;
    else if (Rank[xroot] > Rank[yroot])
        par[yroot] = xroot;
    else {
        par[yroot] = xroot;
        Rank[xroot]++;
    }
}

// Function to compute minimum spanning tree
static void computeMST() {
    // Sort edges in increasing order of weight
    Collections.sort(edges, Comparator.comparingInt(a -> a.first));

    // Go through all the edges
    for (int i = 0; i < m; i++) {
        int u = find(edges.get(i).second >> 10);
        int v = find(edges.get(i).second & ((1 << 10) - 1));

        if (u == v)
            continue;

        // Build minimum spanning tree and store minimum cost
        mst.add(edges.get(i));
        ans += edges.get(i).first;
        Union(u, v);
    }
}

// Function to find the cost of the minimum spanning tree
static void modifiedKruskal(Pair x) {
    initialize();
    ans = 0;
    int sz = zeros.size();

    // Keep the edges which only have zero weights and remove all the other edges
    for (int i = 0; i < sz; i++) {
        Pair front = zeros.poll();
        if (front.first == x.first && front.second == x.second)
            continue;

        // Make union between the vertices of edges which have weight zero and keep them in the queue
        Union(front.first, front.second);
        zeros.add(front);
    }

    // Find the cost of the minimum spanning tree
    for (int i = 0; i < mst.size(); i++) {
        int u = find(mst.get(i).second >> 10);
        int v = find(mst.get(i).second & ((1 << 10) - 1));

        if (u == v)
            continue;

        ans += mst.get(i).first;
        Union(u, v);
    }
}

// Function to handle different queries
static void query(int type, int u, int v) {
    // Update edge weight to 0
    if (type == 2) {
        zeros.add(new Pair(u, v));
        modifiedKruskal(new Pair(-1, -1));
    }
    // Restore edge weight to original value
    else if (type == 3) {
        zeros.add(new Pair(u, v));
        modifiedKruskal(new Pair(u, v));
    } else
        System.out.println(ans);
}

// Driver code
public static void main(String[] args) {
    // Number of nodes and edges
    n = 4;
    m = 4;
    initialize();

    // Initialize data structures
    edges = new ArrayList<>();
    mst = new ArrayList<>();
    zeros = new LinkedList<>();

    // Add edges
    Add_edge(1, 2, 1);
    Add_edge(2, 3, 1);
    Add_edge(3, 4, 1);
    Add_edge(4, 1, 1);

    // Build the minimum spanning tree
    computeMST();

    // Execute queries
    query(2, 1, 2);
    query(1, 0, 0);
    query(3, 1, 2);
    query(1, 0, 0);
}

}

Python3

Python3 implementation of the approach

from collections import deque

N = 2005

To store vertices, edges

and the required answer

n, m, ans = 0, 0, 0

To store parent and rank

par = [0] * N Rank = [0] * N

To store edges and the edges in MST

edges, mst = [], []

To store the edges with weight zero

zeroes = deque()

Function for initialize

def initialize(): for i in range(n + 1): par[i] = i Rank[i] = 0

Function to add edges

def add_edge(u: int, v: int, weight: int): edges.append((weight, (u, v)))

Utility function to find set of an element i

(uses path compression technique)

def find(x: int) -> int: if par[x] != x: par[x] = find(par[x]) return par[x]

Function that performs union of two sets x and y

(uses union by rank)

def union(x: int, y: int): xroot = find(x) yroot = find(y)

if Rank[xroot] < Rank[yroot]:
    par[xroot] = yroot
elif Rank[xroot] > Rank[yroot]:
    par[yroot] = xroot
else:
    par[yroot] = xroot
    Rank[xroot] += 1

Function to compute minimum spanning tree

def compute_MST(): global ans

# Sort edges in increasing order of weight
edges.sort()

# Go through all the edges
for i in range(m):
    u = find(edges[i][1][0])
    v = find(edges[i][1][1])

    if u == v:
        continue

    # Build minimum spanning tree
    # and store minimum cost
    mst.append(edges[i])
    ans += edges[i][0]
    union(u, v)

Function to find the cost of minimum

spanning tree

def modified_kruskal(x): global ans initialize()

# Make answer zero
ans = 0
sz = len(zeroes)

# Keep the edges which only have zero weights
# and remove all the other edges
for i in range(sz):
    front = zeroes[0]
    zeroes.popleft()

    if front[0] == x[0] and front[1] == x[1]:
        continue

    # Make union between the vertices of
    # edges which have weight zero and keep
    # them in queue
    union(front[0], front[1])
    zeroes.append(front)

# Find the cost of the minimum spanning tree
for i in range(len(mst)):
    u = find(mst[i][1][0])
    v = find(mst[i][1][1])

    if u == v:
        continue
    ans += mst[i][0]
    union(u, v)

Function to handle different queries

def query(type: int, u=0, v=0): global ans

# Update edge weight to 0
if type == 2:

    # push edge in zeros
    zeroes.append((u, v))
    modified_kruskal((-1, -1))

# Restore edge weight to original value
elif type == 3:

    # push edge in zeros
    zeroes.append((u, v))
    modified_kruskal((u, v))
else:
    print(ans)

Driver Code

if name == "main":

# Number of nodes and edges
n = 4
m = 4
initialize()

# Add edges
add_edge(1, 2, 1)
add_edge(2, 3, 1)
add_edge(3, 4, 1)
add_edge(4, 1, 1)

# Build the minimum spanning tree
compute_MST()

# Execute queries
query(2, 1, 2)
query(1)
query(3, 1, 2)
query(1)

This code is contributed by

sanjeev2552

C#

using System; using System.Collections.Generic;

class Program { const int N = 2005; static int n, m, ans; static int[] par = new int[N]; static int[] Rank = new int[N]; static List<Tuple<int, Tuple<int, int>>> edges = new List<Tuple<int, Tuple<int, int>>>(); static List<Tuple<int, Tuple<int, int>>> mst = new List<Tuple<int, Tuple<int, int>>>(); static Queue<Tuple<int, int>> zeroes = new Queue<Tuple<int, int>>();

static void Initialize()
{
    // Initialize parent and rank arrays
    for (int i = 0; i <= n; i++)
    {
        par[i] = i;
        Rank[i] = 0;
    }
}

static void AddEdge(int u, int v, int weight)
{
    // Add edge to the list
    edges.Add(new Tuple<int, Tuple<int, int>>(weight, new Tuple<int, int>(u, v)));
}

static int Find(int x)
{
    // Find the root of the set using path compression
    if (par[x] != x)
    {
        par[x] = Find(par[x]);
    }
    return par[x];
}

static void Union(int x, int y)
{
    // Union by rank
    int xroot = Find(x);
    int yroot = Find(y);

    if (Rank[xroot] < Rank[yroot])
    {
        par[xroot] = yroot;
    }
    else if (Rank[xroot] > Rank[yroot])
    {
        par[yroot] = xroot;
    }
    else
    {
        par[yroot] = xroot;
        Rank[xroot]++;
    }
}

static void ComputeMST()
{
    ans = 0;
    // Sort edges in increasing order of weight
    edges.Sort();

    for (int i = 0; i < m; i++)
    {
        int u = Find(edges[i].Item2.Item1);
        int v = Find(edges[i].Item2.Item2);

        if (u == v)
        {
            // Skip if adding the edge creates a cycle
            continue;
        }

        // Build minimum spanning tree and update cost
        mst.Add(edges[i]);
        ans += edges[i].Item1;
        Union(u, v);
    }
}

static void ModifiedKruskal(Tuple<int, int> x)
{
    Initialize();
    ans = 0;
    int sz = zeroes.Count;

    for (int i = 0; i < sz; i++)
    {
        Tuple<int, int> front = zeroes.Dequeue();

        if (front.Item1 == x.Item1 && front.Item2 == x.Item2)
        {
            continue;
        }

        Union(front.Item1, front.Item2);
        zeroes.Enqueue(front);
    }

    for (int i = 0; i < mst.Count; i++)
    {
        int u = Find(mst[i].Item2.Item1);
        int v = Find(mst[i].Item2.Item2);

        if (u == v)
        {
            continue;
        }
        ans += mst[i].Item1;
        Union(u, v);
    }
}

static void Query(int type, int u = 0, int v = 0)
{
    if (type == 2)
    {
        // Update edge weight to 0
        zeroes.Enqueue(new Tuple<int, int>(u, v));
        ModifiedKruskal(new Tuple<int, int>(-1, -1));
    }
    else if (type == 3)
    {
        // Restore edge weight to original value
        zeroes.Enqueue(new Tuple<int, int>(u, v));
        ModifiedKruskal(new Tuple<int, int>(u, v));
    }
    else
    {
        // Print the cost of the minimum spanning tree
        Console.WriteLine(ans);
    }
}

static void Main()
{
    n = 4;
    m = 4;
    Initialize();

    // Add edges
    AddEdge(1, 2, 1);
    AddEdge(2, 3, 1);
    AddEdge(3, 4, 1);
    AddEdge(4, 1, 1);

    // Build the minimum spanning tree
    ComputeMST();

    // Execute queries
    Query(2, 1, 2);
    Query(1);
    Query(3, 1, 2);
    Query(1);
}

}

JavaScript

// JS implementation of the approach const N = 2005; let n = 0, m = 0, ans = 0;

// To store vertices, edges // and the required answer const par = new Array(N), Rank = new Array(N), edges = [], mst = [], zeroes = [];

// Function for initialize function initialize() { for (let i = 0; i <= n; i++) { par[i] = i; Rank[i] = 0; } }

// Function to add edges function add_edge(u, v, weight) { edges.push([weight, [u, v]]); }

// Utility function to find set of an element i // (uses path compression technique) function find(x) { if (par[x] !== x) { par[x] = find(par[x]); } return par[x]; }

// Function that performs union of two sets x and y // (uses union by rank) function union(x, y) { const xroot = find(x); const yroot = find(y);

if (Rank[xroot] < Rank[yroot]) {
    par[xroot] = yroot;
} else if (Rank[xroot] > Rank[yroot]) {
    par[yroot] = xroot;
} else {
    par[yroot] = xroot;
    Rank[xroot]++;
}

}

// Function to compute minimum spanning tree function compute_MST() {

 // Sort edges in increasing order of weight
edges.sort((a, b) => a[0] - b[0]);

   // Go through all the edges
for (let i = 0; i < m; i++) {
    const u = find(edges[i][1][0]);
    const v = find(edges[i][1][1]);
    if (u === v) continue;
    
     // Build minimum spanning tree
   // and store minimum cost
    mst.push(edges[i]);
    ans += edges[i][0];
    union(u, v);
}

}

// Function to find the cost of minimum // spanning tree function modified_kruskal(x) { initialize();

 // Make answer zero
ans = 0;
const sz = zeroes.length;

   // Keep the edges which only have zero weights

// and remove all the other edges for (let i = 0; i < sz; i++) { const front = zeroes.shift(); if (front[0] === x[0] && front[1] === x[1]) continue;

      // Make union between the vertices of
   // edges which have weight zero and keep
   // them in queue
    union(front[0], front[1]);
    zeroes.push(front);
}

  // Find the cost of the minimum spanning tree
for (let i = 0; i < mst.length; i++) {
    const u = find(mst[i][1][0]);
    const v = find(mst[i][1][1]);
    if (u === v) continue;
    ans += mst[i][0];
    union(u, v);
}

}

// Function to handle different queries function query(type, u = 0, v = 0) {

   // Update edge weight to 0
if (type === 2) {

       // push edge in zeros
    zeroes.push([u, v]);
    modified_kruskal([-1, -1]);
    
}// Restore edge weight to original value
else if (type === 3) {
       // push edge in zeros
    zeroes.push([u, v]);
    modified_kruskal([u, v]);
} else {
    console.log(ans);
}

}

// Number of nodes and edges n = 4; m = 4; initialize(); add_edge(1, 2, 1); add_edge(2, 3, 1); add_edge(3, 4, 1); add_edge(4, 1, 1);

// Build the minimum spanning tree compute_MST();

query(2, 1, 2); query(1); query(3, 1, 2); query(1);

// This code is contributed by lokeshpotta20.

`

**Time Complexity: O(N) per query, where N is the total number of nodes in the graph.
**Auxiliary Space: O(N)