Find the weight of the minimum spanning tree

12 Aug, 2021
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:  
query(1) -> Find the weight of the minimum spanning tree.query(2, x, y) -> Change the weight of the edge between the nodes x and y to 0.query(3, x, y) -> Restore the weight of the edge between the nodes x and y to its original weight.
query(1) -> Find the weight of the minimum spanning tree.
query(2, x, y) -> Change the weight of the edge between the nodes x and y to 0.
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 3Input:  
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++
Python3
// C++ implementation of the approach#include <bits/stdc++.h>using namespace std;#define N 2005 // To store vertices, edges// and the required answerint n, m, ans; // To store parent and rankint par[N], Rank[N]; // To store edges and the edges in MSTvector<pair<int, pair<int, int> > > edges, mst; // To store the edges with weight zeroqueue<pair<int, int> > zeros; // Function for initializevoid initialize(){    for (int i = 0; i <= n; i++) {        par[i] = i;        Rank[i] = 0;    }} // Function to add edgesvoid 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 treevoid 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 treevoid 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 queriesvoid 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 codeint 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 implementation of the approachfrom collections import deque N = 2005 # To store vertices, edges# and the required answern, m, ans = 0, 0, 0 # To store parent and rankpar = [0] * NRank = [0] * N # To store edges and the edges in MSTedges, mst = [], [] # To store the edges with weight zerozeroes = deque() # Function for initializedef initialize():    for i in range(n + 1):        par[i] = i        Rank[i] = 0 # Function to add edgesdef 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 treedef 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 treedef 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 queriesdef 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 Codeif __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
2
3
 
Time Complexity: O(N) per query, where N is the total number of nodes in the graph.Auxiliary Space: O(N) 
sanjeev2552
pankajsharmagfg
Kruskal'sAlgorithm
Minimum Spanning Tree
Competitive Programming
Data Structures
Graph
Data Structures
Graph
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.