GeeksforGeeks App
Open App
Browser
Continue

# Find the weight of the minimum spanning tree

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:

3
Input:

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

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 ``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 > > edges, mst;` `// To store the edges with weight zero``queue > 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;``}`

## 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`

## 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.`

Output:

```2
3```

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

My Personal Notes arrow_drop_up