In a city, there are many hospitals. Each hospital is connected to some other hospitals, represented using an adjacency list adj[][], where adj[i] contains all hospitals directly connected to the i-th hospital. Our task is to ensure that all hospitals are connected, either directly or indirectly to each other. In one operation, we can remove an existing link and reconnect it between two previously disconnected hospitals. Determine the minimum number of operations required to make the entire network connected. If it is impossible, return -1.
Examples:
Input: adj[][] = [[1, 2], [0, 2], [0, 1], []] Output: 1 Explanation: Remove the connection between hospitals 1 and 2 and connect the hospitals 1 and 3.
Input: adj[][]= [[1, 2], [0], [0, 3], [2, 4],[3]] Output: 0 Explanation: All hospitals are already connected directly or indirectly. No rearrangement of connections is required.
Intuition: To connect all hospitals into one complete network, we must ensure that every hospital is reachable from every other hospital and that the entire system forms a single connected component. To connect all disconnected groups of hospitals, we need extra edges. These extra edges come from redundant connections- links that connect hospitals already reachable through some other path. If the number of extra edges is enough to connect all disconnected groups, i.e., if extra edges ≥ (disconnected components − 1), then we can rebuild the network. In that case, the minimum number of operations needed will also be (disconnected components − 1) because that’s exactly how many new links are required to make the whole system fully connected.
[Approach 1] Using Disjoint Set
We use a Disjoint Set Union (DSU), because it helps us efficiently identify if two hospitals are already connected (directly or indirectly) and also merge two disconnected hospitals into one connected component whenever an edge exists.
While traversing, if two hospitals already belong to the same component, it means the current connection is redundant or extra. Otherwise, we merge them into one set. By the time we finish processing all connections, we know exactly how many extra edges we have. Next, to find how many disconnected components exist, we check each hospital and see whether it has a different parent. If a hospital’s parent is different from others, it belongs to a different component.
After that, we simply compare the number of extra edges with the number of disconnected components to determine whether the entire network can be connected.
C++
//Driver Code Starts#include<iostream>#include<vector>usingnamespacestd;//Driver Code EndsclassDisjointSet{vector<int>rank,parent,size;public:DisjointSet(intn){rank.resize(n+1,0);parent.resize(n+1);size.resize(n+1);for(inti=0;i<=n;i++){parent[i]=i;size[i]=1;}}// Find the ultimate parent of a node (with path compression)intfindUPar(intnode){if(node==parent[node])returnnode;returnparent[node]=findUPar(parent[node]);}// Union by sizevoidunionBySize(intu,intv){intulpU=findUPar(u);intulpV=findUPar(v);if(ulpU==ulpV)return;if(size[ulpU]<size[ulpV]){parent[ulpU]=ulpV;size[ulpV]+=size[ulpU];}else{parent[ulpV]=ulpU;size[ulpU]+=size[ulpV];}}};// Function to find minimum operations requiredintminConnect(vector<vector<int>>&adj){intn=adj.size();DisjointSetds(n);intextra=0;// Traverse all links in adjacency listfor(intu=0;u<n;u++){for(intv:adj[u]){// To avoid processing duplicate edges if(u<v){// If both hospitals are already connected,//mark this link as extraif(ds.findUPar(u)==ds.findUPar(v))extra++;elseds.unionBySize(u,v);}}}// Count disconnected componentsintcomponents=0;for(inti=0;i<n;i++){if(ds.findUPar(i)==i){components++;}}// If enough extra links exist to connect all componentsif(extra>=components-1)returncomponents-1;elsereturn-1;}//Driver Code Startsintmain(){vector<vector<int>>adj={{{1,2},{0,2},{0,1},{}}};cout<<minConnect(adj)<<endl;return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.ArrayList;importjava.util.Collections;//Driver Code EndsclassDisjointSet{ArrayList<Integer>rank,parent,size;DisjointSet(intn){rank=newArrayList<>(Collections.nCopies(n+1,0));parent=newArrayList<>(n+1);size=newArrayList<>(n+1);for(inti=0;i<=n;i++){parent.add(i);size.add(1);}}// Find the ultimate parent of a node (with path compression)intfindUPar(intnode){if(node==parent.get(node))returnnode;parent.set(node,findUPar(parent.get(node)));returnparent.get(node);}// Union by sizevoidunionBySize(intu,intv){intulpU=findUPar(u);intulpV=findUPar(v);if(ulpU==ulpV)return;if(size.get(ulpU)<size.get(ulpV)){parent.set(ulpU,ulpV);size.set(ulpV,size.get(ulpV)+size.get(ulpU));}else{parent.set(ulpV,ulpU);size.set(ulpU,size.get(ulpU)+size.get(ulpV));}}}publicclassGFG{// Function to find minimum operations requiredstaticintminConnect(ArrayList<ArrayList<Integer>>adj){intn=adj.size();DisjointSetds=newDisjointSet(n);intextra=0;// Traverse all links in adjacency listfor(intu=0;u<n;u++){for(intv:adj.get(u)){// avoid duplicate edgesif(u<v){if(ds.findUPar(u)==ds.findUPar(v))extra++;elseds.unionBySize(u,v);}}}// Count disconnected componentsintcomponents=0;for(inti=0;i<n;i++){if(ds.findUPar(i)==i)components++;}// Check if extra edges are enoughif(extra>=components-1)returncomponents-1;return-1;}//Driver Code Starts// Function to add edges in adjacency liststaticvoidaddEdge(ArrayList<ArrayList<Integer>>adj,intu,intv){adj.get(u).add(v);adj.get(v).add(u);}publicstaticvoidmain(String[]args){intV=4;ArrayList<ArrayList<Integer>>adj=newArrayList<>();for(inti=0;i<V;i++)adj.add(newArrayList<>());// Adding edgesaddEdge(adj,0,1);addEdge(adj,0,2);addEdge(adj,1,2);System.out.println(minConnect(adj));}}//Driver Code Ends
Python
classDisjointSet:def__init__(self,n):self.rank=[0]*(n+1)self.parent=[iforiinrange(n+1)]self.size=[1]*(n+1)# Find the ultimate parent of a node (with path compression)deffindUPar(self,node):ifnode==self.parent[node]:returnnodeself.parent[node]=self.findUPar(self.parent[node])returnself.parent[node]# Union by sizedefunionBySize(self,u,v):ulpU=self.findUPar(u)ulpV=self.findUPar(v)ifulpU==ulpV:returnifself.size[ulpU]<self.size[ulpV]:self.parent[ulpU]=ulpVself.size[ulpV]+=self.size[ulpU]else:self.parent[ulpV]=ulpUself.size[ulpU]+=self.size[ulpV]# Function to find minimum operations requireddefminConnect(adj):n=len(adj)ds=DisjointSet(n)extra=0# Traverse all links in adjacency listforuinrange(n):forvinadj[u]:# To avoid processing duplicate edges ifu<v:# If both hospitals are already connected,#mark this link as extraifds.findUPar(u)==ds.findUPar(v):extra+=1else:ds.unionBySize(u,v)# Count disconnected components using DFScomponents=sum(1foriinrange(n)ifds.findUPar(i)==i)# If enough extra links exist to connect all componentsifextra>=components-1:returncomponents-1else:return-1#Driver Code Startsif__name__=="__main__":# Adjacency listadj=[[1,2],[0,2],[0,1],[]]print(minConnect(adj))#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;//Driver Code EndsclassDisjointSet{List<int>rank,parent,size;publicDisjointSet(intn){rank=newList<int>(newint[n+1]);parent=newList<int>(n+1);size=newList<int>(n+1);for(inti=0;i<=n;i++){parent.Add(i);size.Add(1);}}// Find the ultimate parent of a node (with path compression)publicintfindUPar(intnode){if(node==parent[node])returnnode;parent[node]=findUPar(parent[node]);returnparent[node];}// Union by sizepublicvoidunionBySize(intu,intv){intulpU=findUPar(u);intulpV=findUPar(v);if(ulpU==ulpV)return;if(size[ulpU]<size[ulpV]){parent[ulpU]=ulpV;size[ulpV]=size[ulpV]+size[ulpU];}else{parent[ulpV]=ulpU;size[ulpU]=size[ulpU]+size[ulpV];}}}classGFG{// Function to find minimum operations requiredstaticintminConnect(List<List<int>>adj){intn=adj.Count;DisjointSetds=newDisjointSet(n);intextra=0;// Traverse all links in adjacency listfor(intu=0;u<n;u++){foreach(intvinadj[u]){// avoid duplicate edgesif(u<v){if(ds.findUPar(u)==ds.findUPar(v))extra++;elseds.unionBySize(u,v);}}}// Count disconnected componentsintcomponents=0;for(inti=0;i<n;i++){if(ds.findUPar(i)==i)components++;}// Check if extra edges are enoughif(extra>=components-1)returncomponents-1;return-1;}//Driver Code Starts// Function to add edges in adjacency liststaticvoidaddEdge(List<List<int>>adj,intu,intv){adj[u].Add(v);adj[v].Add(u);}publicstaticvoidMain(string[]args){intV=4;List<List<int>>adj=newList<List<int>>();for(inti=0;i<V;i++)adj.Add(newList<int>());// Adding edgesaddEdge(adj,0,1);addEdge(adj,0,2);addEdge(adj,1,2);Console.WriteLine(minConnect(adj));}}//Driver Code Ends
JavaScript
classDisjointSet{constructor(n){this.rank=newArray(n+1).fill(0);this.parent=Array.from({length:n+1},(_,i)=>i);this.size=newArray(n+1).fill(1);}// Find the ultimate parent of a node (with path compression)findUPar(node){if(node===this.parent[node])returnnode;this.parent[node]=this.findUPar(this.parent[node]);returnthis.parent[node];}// Union by sizeunionBySize(u,v){letulpU=this.findUPar(u);letulpV=this.findUPar(v);if(ulpU===ulpV)return;if(this.size[ulpU]<this.size[ulpV]){this.parent[ulpU]=ulpV;this.size[ulpV]+=this.size[ulpU];}else{this.parent[ulpV]=ulpU;this.size[ulpU]+=this.size[ulpV];}}}// Function to find minimum operations requiredfunctionminConnect(adj){constn=adj.length;constds=newDisjointSet(n);letextra=0;// Traverse all links in adjacency listfor(letu=0;u<n;u++){for(letvofadj[u]){// To avoid processing duplicate edges if(u<v){// If both hospitals are already connected,//mark this link as extraif(ds.findUPar(u)===ds.findUPar(v))extra++;elseds.unionBySize(u,v);}}}// Count disconnected components using DFSletcomponents=0;for(leti=0;i<n;i++){if(ds.findUPar(i)===i)components++;}// If enough extra links exist to connect all componentsreturnextra>=components-1?components-1:-1;}//Driver Code Starts//Driver Code// Adjacency listconstadj=[[1,2],[0,2],[0,1],[]];console.log(minConnect(adj));//Driver Code Ends
Output
1
Time Complexity: O(V+E), V = number of hospitals (nodes), E = total number of links (edges) Auxiliary Space: O (V + E)
[Approach 2] Using DFS
According to the MST property, a component with V vertices requires exactly (V − 1) edges to stay fully connected. If more edges than required are present, those extra edges are redundant and can be reused to connect other disconnected hospitals. We compute the number of extra edges using: Extra Edges = Total Edges − (Vertices − Disconnected Components)
After this, we simply find the number of disconnected components using DFS and check whether the extra edges are enough to connect them. To connect all components, we need (Disconnected Components − 1) edges. If the extra edges are at least this number, all hospitals can be connected; otherwise, it is impossible.
C++
//Driver Code Starts#include<iostream>#include<vector>usingnamespacestd;//Driver Code Ends// DFS function to visit all hospitals in a connected componentvoiddfs(intstart,vector<vector<int>>&adj,vector<bool>&visited){visited[start]=true;for(intneighbor:adj[start]){if(!visited[neighbor])dfs(neighbor,adj,visited);}}intminConnect(vector<vector<int>>&adj){intV=adj.size();vector<bool>visited(V,false);intedges=0;// Count total number of edges for(inti=0;i<V;i++)edges+=adj[i].size();edges/=2;// Count disconnected components using DFSintcomponents=0;for(inti=0;i<V;i++){if(!visited[i]){components++;dfs(i,adj,visited);}}// If total edges are less than (V - 1), it's impossible to connect allif(edges<V-1)return-1;// Calculate redundant (extra) edgesintextra=edges-(V-components);// If enough extra edges exist to connect all componentsif(extra>=(components-1))returncomponents-1;return-1;}//Driver Code Startsintmain(){vector<vector<int>>adj={{{1,2},{0,2},{0,1},{}}};cout<<minConnect(adj);return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.ArrayList;publicclassGFG{//Driver Code Ends// DFS function to visit all hospitals in a connected componentstaticvoiddfs(intstart,ArrayList<ArrayList<Integer>>adj,boolean[]visited){visited[start]=true;for(intneighbor:adj.get(start)){if(!visited[neighbor])dfs(neighbor,adj,visited);}}staticintminConnect(ArrayList<ArrayList<Integer>>adj){intV=adj.size();boolean[]visited=newboolean[V];intedges=0;// Count total number of edges for(inti=0;i<V;i++)edges+=adj.get(i).size();edges/=2;// Count disconnected components using DFSintcomponents=0;for(inti=0;i<V;i++){if(!visited[i]){components++;dfs(i,adj,visited);}}// If total edges are less than (V - 1), it's impossible to connect allif(edges<V-1)return-1;// Calculate redundant (extra) edgesintextra=edges-(V-components);// If enough extra edges exist to connect all componentsif(extra>=(components-1))returncomponents-1;return-1;}//Driver Code StartsstaticvoidaddEdge(ArrayList<ArrayList<Integer>>adj,intu,intv){adj.get(u).add(v);adj.get(v).add(u);}publicstaticvoidmain(String[]args){intn=4;ArrayList<ArrayList<Integer>>adj=newArrayList<>();for(inti=0;i<n;i++)adj.add(newArrayList<>());addEdge(adj,0,1);addEdge(adj,0,2);addEdge(adj,1,2);System.out.println(minConnect(adj));}}//Driver Code Ends
Python
# DFS function to visit all hospitals in a connected componentdefdfs(start,adj,visited):visited[start]=Trueforneighborinadj[start]:ifnotvisited[neighbor]:dfs(neighbor,adj,visited)defminConnect(adj):V=len(adj)visited=[False]*Vedges=0# Count total number of edges foriinrange(V):edges+=len(adj[i])edges//=2# Count disconnected components using DFScomponents=0foriinrange(V):ifnotvisited[i]:components+=1dfs(i,adj,visited)# If total edges are less than (V - 1), it's impossible to connect allifedges<V-1:return-1# Calculate redundant (extra) edgesextra=edges-(V-components);# If enough extra edges exist to connect all componentsifextra>=(components-1):returncomponents-1return-1#Driver Code Startsif__name__=="__main__":adj=[[1,2],[0,2],[0,1],[]]print(minConnect(adj))#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;classGFG{//Driver Code Ends// DFS function to visit all hospitals in a connected componentstaticvoiddfs(intstart,List<List<int>>adj,bool[]visited){visited[start]=true;foreach(intneighborinadj[start]){if(!visited[neighbor])dfs(neighbor,adj,visited);}}staticintminConnect(List<List<int>>adj){intV=adj.Count;bool[]visited=newbool[V];intedges=0;// Count total number of edges for(inti=0;i<V;i++)edges+=adj[i].Count;edges/=2;// Count disconnected components using DFSintcomponents=0;for(inti=0;i<V;i++){if(!visited[i]){components++;dfs(i,adj,visited);}}// If total edges are less than (V - 1), it's impossible to connect allif(edges<V-1)return-1;// Calculate redundant (extra) edgesintextra=edges-(V-components);// If enough extra edges exist to connect all componentsif(extra>=(components-1))returncomponents-1;return-1;}//Driver Code StartsstaticvoidaddEdge(List<List<int>>adj,intu,intv){adj[u].Add(v);adj[v].Add(u);}staticvoidMain(){intn=4;List<List<int>>adj=newList<List<int>>();for(inti=0;i<n;i++)adj.Add(newList<int>());addEdge(adj,0,1);addEdge(adj,0,2);addEdge(adj,1,2);Console.WriteLine(minConnect(adj));}}//Driver Code Ends
JavaScript
// DFS function to visit all hospitals in a connected componentfunctiondfs(start,adj,visited){visited[start]=true;for(letneighborofadj[start]){if(!visited[neighbor])dfs(neighbor,adj,visited);}}functionminConnect(adj){constV=adj.length;constvisited=Array(V).fill(false);letedges=0;// Count total number of edges for(leti=0;i<V;i++)edges+=adj[i].length;edges=Math.floor(edges/2);// Count disconnected components using DFSletcomponents=0;for(leti=0;i<V;i++){if(!visited[i]){components++;dfs(i,adj,visited);}}// If total edges are less than (V - 1), it's impossible to connect allif(edges<V-1)return-1;// Calculate redundant (extra) edgesletextra=edges-(V-components);// If enough extra edges exist to connect all componentsif(extra>=(components-1))returncomponents-1;return-1;}//Driver Code Starts// Driver Codeconstadj=[[1,2],[0,2],[0,1],[]];console.log(minConnect(adj));//Driver Code Ends