Open In App

Minimize count of connections required to be rearranged to make all the computers connected

Improve
Improve
Like Article
Like
Save
Share
Report

Given an integer N, denoting the number of computers connected by cables forming a network and a 2D array connections[][], with each row (i, j) representing a connection between ith and jth computer, the task is to connect all the computers either directly or indirectly by removing any of the given connections and connecting two disconnected computers If it’s not possible to connect all the computers, print -1. Otherwise, print the minimum number of such operations required.

Examples:

Input: N = 4, connections[][] = {{0, 1}, {0, 2}, {1, 2}}
Output: 1
Explanation: Remove the connection between computers 1 and 2 and connect the computers 1 and 3.

Input: N = 5, connections[][] = {{0, 1}, {0, 2}, {3, 4}, {2, 3}}
Output: 0

Using Disjoint Set And Adjacency List :

  Here We use disjoint set to calculate extra connections between computers then using disjoint set method 
call findupar() then we will calculate the total number of components of graph.
Now.
we have k i.e extra edges
&
n i.e number of components in graph.

if((totalcomponents-1)<=k)return totalcomponents-1; // totalcomponents-1 must be less then extra edges in all
components to connect all to each other.
else return -1; // if not return -1.

Follow the steps below to solve the problem:

  •  Make adjacency list from given 2D array.
  •  Call disjoint class with given number of computers.
  •  Calculate total number of components in graph using dfs.
  •  Last step check totalcomponents – 1 <= totalnumberofextraedges.

Below is the implementation of the above approach:

C++




#include <bits/stdc++.h>
#include <iostream>
 
using namespace std;
 
class DisjointSet {
    vector<int> rank, parent, size;
 
public:
    DisjointSet(int n)
    {
        rank.resize(n + 1, 0);
        parent.resize(n + 1);
        size.resize(n + 1);
        for (int i = 0; i <= n; i++) {
            parent[i] = i;
            size[i] = 1;
        }
    }
 
    int findUPar(int node)
    {
        if (node == parent[node])
            return node;
        return parent[node] = findUPar(parent[node]);
    }
 
    void unionByRank(int u, int v)
    {
        int ulp_u = findUPar(u);
        int ulp_v = findUPar(v);
        if (ulp_u == ulp_v)
            return;
        if (rank[ulp_u] < rank[ulp_v]) {
            parent[ulp_u] = ulp_v;
        }
        else if (rank[ulp_v] < rank[ulp_u]) {
            parent[ulp_v] = ulp_u;
        }
        else {
            parent[ulp_v] = ulp_u;
            rank[ulp_u]++;
        }
    }
 
    void unionBySize(int u, int v)
    {
        int ulp_u = findUPar(u);
        int ulp_v = findUPar(v);
        if (ulp_u == ulp_v)
            return;
        if (size[ulp_u] < size[ulp_v]) {
            parent[ulp_u] = ulp_v;
            size[ulp_v] += size[ulp_u];
        }
        else {
            parent[ulp_v] = ulp_u;
            size[ulp_u] += size[ulp_v];
        }
    }
};
 
void dfs(int start, vector<int> adj[], vector<bool>& vis)
{
    if (vis[start])
        return;
    vis[start] = 1;
    for (auto it : adj[start]) {
        dfs(it, adj, vis);
    }
}
 
int main(){
    int n = 6;
    vector<vector<int> > connections{
      {0,1},{0,2},{0,3},{1,2},{1,3}
    };
    vector<int> adj[n + 1];
    for (int i = 0; i < connections.size(); i++) {
        adj[connections[i][0]].push_back(connections[i][1]);
        adj[connections[i][1]].push_back(connections[i][0]);
    }
    DisjointSet ds(n);
    int extra = 0;
    for (int i = 0; i < connections.size(); i++) {
        if (ds.findUPar(connections[i][0])
            == ds.findUPar(connections[i][1]))
            ++extra;
        ds.unionBySize(connections[i][0],
                       connections[i][1]);
    }
    vector<bool> vis(n, 0);
    dfs(0, adj, vis);
    int cnt = 0;
    for (int i = 0; i < n; i++) {
        if (!vis[i]) {
            ++cnt;
            dfs(i, adj, vis);
        }
    }
    if (cnt <= extra) {
        cout << cnt << endl;
    }
    else {
        cout << "All computer can not be connect "
             << endl;
        cout<<-1<<endl;
    }
  //code and approach contributed by Sanket Gode.
    return 0;
}


Java




import java.util.*;
 
class DisjointSet {
    private int[] rank, parent, size;
 
    public DisjointSet(int n)
    {
        rank = new int[n + 1];
        parent = new int[n + 1];
        size = new int[n + 1];
        for (int i = 0; i <= n; i++) {
            parent[i] = i;
            size[i] = 1;
        }
    }
 
    public int findUPar(int node)
    {
        if (node == parent[node])
            return node;
        return parent[node] = findUPar(parent[node]);
    }
 
    public void unionByRank(int u, int v)
    {
        int ulp_u = findUPar(u);
        int ulp_v = findUPar(v);
        if (ulp_u == ulp_v)
            return;
        if (rank[ulp_u] < rank[ulp_v]) {
            parent[ulp_u] = ulp_v;
        }
        else if (rank[ulp_v] < rank[ulp_u]) {
            parent[ulp_v] = ulp_u;
        }
        else {
            parent[ulp_v] = ulp_u;
            rank[ulp_u]++;
        }
    }
 
    public void unionBySize(int u, int v)
    {
        int ulp_u = findUPar(u);
        int ulp_v = findUPar(v);
        if (ulp_u == ulp_v)
            return;
        if (size[ulp_u] < size[ulp_v]) {
            parent[ulp_u] = ulp_v;
            size[ulp_v] += size[ulp_u];
        }
        else {
            parent[ulp_v] = ulp_u;
            size[ulp_u] += size[ulp_v];
        }
    }
}
 
public class GFG {
 
    public static void
    dfs(int start, ArrayList<Integer>[] adj, boolean[] vis)
    {
        if (vis[start])
            return;
        vis[start] = true;
        for (int it : adj[start]) {
            dfs(it, adj, vis);
        }
    }
 
    public static void main(String[] args)
    {
        int n = 6;
        ArrayList<int[]> connections
            = new ArrayList<int[]>(Arrays.asList(
                new int[] { 0, 1 }, new int[] { 0, 2 },
                new int[] { 0, 3 }, new int[] { 1, 2 },
                new int[] { 1, 3 }));
        ArrayList<Integer>[] adj = new ArrayList[n + 1];
        for (int i = 0; i <= n; i++) {
            adj[i] = new ArrayList<>();
        }
        for (int i = 0; i < connections.size(); i++) {
            int u = connections.get(i)[0],
                v = connections.get(i)[1];
            adj[u].add(v);
            adj[v].add(u);
        }
        DisjointSet ds = new DisjointSet(n);
        int extra = 0;
        for (int i = 0; i < connections.size(); i++) {
            int u = connections.get(i)[0],
                v = connections.get(i)[1];
            if (ds.findUPar(u) == ds.findUPar(v))
                ++extra;
            ds.unionBySize(u, v);
        }
        boolean[] vis = new boolean[n];
        dfs(0, adj, vis);
        int cnt = 0;
        for (int i = 0; i < n; i++) {
            if (!vis[i]) {
                ++cnt;
                dfs(i, adj, vis);
            }
        }
        if (cnt <= extra) {
            System.out.println(cnt);
        }
        else {
            System.out.println(
                "All computer can not be connect ");
            System.out.println(-1);
        }
      // Code is Contributed by Vikas Bishnoi
    }
}


Python3




from typing import List
 
class DisjointSet:
    def __init__(self, n: int) -> None:
        self.rank = [0] * (n + 1)
        self.parent = list(range(n + 1))
        self.size = [1] * (n + 1)
 
    def findUPar(self, node: int) -> int:
        if node == self.parent[node]:
            return node
        self.parent[node] = self.findUPar(self.parent[node])
        return self.parent[node]
 
    def unionByRank(self, u: int, v: int) -> None:
        ulp_u = self.findUPar(u)
        ulp_v = self.findUPar(v)
        if ulp_u == ulp_v:
            return
        if self.rank[ulp_u] < self.rank[ulp_v]:
            self.parent[ulp_u] = ulp_v
        elif self.rank[ulp_v] < self.rank[ulp_u]:
            self.parent[ulp_v] = ulp_u
        else:
            self.parent[ulp_v] = ulp_u
            self.rank[ulp_u] += 1
 
    def unionBySize(self, u: int, v: int) -> None:
        ulp_u = self.findUPar(u)
        ulp_v = self.findUPar(v)
        if ulp_u == ulp_v:
            return
        if self.size[ulp_u] < self.size[ulp_v]:
            self.parent[ulp_u] = ulp_v
            self.size[ulp_v] += self.size[ulp_u]
        else:
            self.parent[ulp_v] = ulp_u
            self.size[ulp_u] += self.size[ulp_v]
 
def dfs(start: int, adj: List[List[int]], vis: List[bool]) -> None:
    if vis[start]:
        return
    vis[start] = True
    for it in adj[start]:
        dfs(it, adj, vis)
 
if __name__ == '__main__':
    n = 6
    connections = [[0,1],[0,2],[0,3],[1,2],[1,3]]
    adj = [[] for _ in range(n + 1)]
    for u, v in connections:
        adj[u].append(v)
        adj[v].append(u)
    ds = DisjointSet(n)
    extra = 0
    for u, v in connections:
        if ds.findUPar(u) == ds.findUPar(v):
            extra += 1
        ds.unionBySize(u, v)
    vis = [False] * n
    dfs(0, adj, vis)
    cnt = 0
    for i in range(n):
        if not vis[i]:
            cnt += 1
            dfs(i, adj, vis)
    if cnt <= extra:
        print(cnt)
    else:
        print("All computer can not be connect")
        print(-1)


C#




// Importing required libraries
using System;
using System.Collections.Generic;
 
// Creating a DisjointSet class
class DisjointSet
{
   
    // Defining class variables
    List<int> rank, parent, size;
   
    // Constructor to initialize the class variables
    public DisjointSet(int n)
    {
        rank = new List<int>();
        parent = new List<int>();
        size = new List<int>();
        for (int i = 0; i <= n; i++) {
            rank.Add(0);
            parent.Add(i);
            size.Add(1);
        }
    }
 
    // Method to find the parent of a node using path
    // compression
    public int FindUPar(int node)
    {
        if (node == parent[node]) {
            return node;
        }
        parent[node] = FindUPar(parent[node]);
        return parent[node];
    }
 
    // Method to perform union by rank
    public void UnionByRank(int u, int v)
    {
        int ulp_u = FindUPar(u);
        int ulp_v = FindUPar(v);
        if (ulp_u == ulp_v) {
            return;
        }
        if (rank[ulp_u] < rank[ulp_v]) {
            parent[ulp_u] = ulp_v;
        }
        else if (rank[ulp_v] < rank[ulp_u]) {
            parent[ulp_v] = ulp_u;
        }
        else {
            parent[ulp_v] = ulp_u;
            rank[ulp_u]++;
        }
    }
 
    // Method to perform union by size
    public void UnionBySize(int u, int v)
    {
        int ulp_u = FindUPar(u);
        int ulp_v = FindUPar(v);
        if (ulp_u == ulp_v) {
            return;
        }
        if (size[ulp_u] < size[ulp_v]) {
            parent[ulp_u] = ulp_v;
            size[ulp_v] += size[ulp_u];
        }
        else {
            parent[ulp_v] = ulp_u;
            size[ulp_u] += size[ulp_v];
        }
    }
}
 
// Main function
class Program {
    static void dfs(int start, List<int>[] adj,
                    ref List<bool> vis)
    {
        if (vis[start]) {
            return;
        }
        vis[start] = true;
        foreach(int it in adj[start])
        {
            dfs(it, adj, ref vis);
        }
    }
    static void Main(string[] args)
    {
        // Initializing the input values
        int n = 6;
        List<List<int> > connections = new List<List<int> >{
            new List<int>{ 0, 1 }, new List<int>{ 0, 2 },
            new List<int>{ 0, 3 }, new List<int>{ 1, 2 },
            new List<int>{ 1, 3 }
        };
        List<int>[] adj = new List<int>[ n + 1 ];
        for (int i = 0; i <= n; i++) {
            adj[i] = new List<int>();
        }
        foreach(List<int> con in connections)
        {
            adj[con[0]].Add(con[1]);
            adj[con[1]].Add(con[0]);
        }
        DisjointSet ds = new DisjointSet(n);
        int extra = 0;
        foreach(List<int> con in connections)
        {
            if (ds.FindUPar(con[0])
                == ds.FindUPar(con[1])) {
                extra++;
            }
            ds.UnionBySize(con[0], con[1]);
        }
        List<bool> visited = new List<bool>();
        for (int i = 0; i <= n; i++) {
            visited.Add(false);
        }
        int count = 0;
        for (int i = 0; i < n; i++) {
            if (!visited[i]) {
                dfs(i, adj, ref visited);
                count++;
            }
        }
        if (extra >= count - 1) {
            Console.WriteLine(count - 1);
        }
        else {
            Console.WriteLine("Not possible");
        }
    }
}


Javascript




class DisjointSet {
    constructor(n) {
        this.rank = new Array(n + 1).fill(0);
        this.parent = new Array(n + 1);
        this.size = new Array(n + 1);
        for (let i = 0; i <= n; i++) {
            this.parent[i] = i;
            this.size[i] = 1;
        }
    }
 
    findUPar(node) {
        if (node === this.parent[node])
            return node;
        return this.parent[node] = this.findUPar(this.parent[node]);
    }
 
    unionByRank(u, v) {
        const ulp_u = this.findUPar(u);
        const ulp_v = this.findUPar(v);
        if (ulp_u === ulp_v)
            return;
        if (this.rank[ulp_u] < this.rank[ulp_v]) {
            this.parent[ulp_u] = ulp_v;
        } else if (this.rank[ulp_v] < this.rank[ulp_u]) {
            this.parent[ulp_v] = ulp_u;
        } else {
            this.parent[ulp_v] = ulp_u;
            this.rank[ulp_u]++;
        }
    }
 
    unionBySize(u, v) {
        const ulp_u = this.findUPar(u);
        const ulp_v = this.findUPar(v);
        if (ulp_u === ulp_v)
            return;
        if (this.size[ulp_u] < this.size[ulp_v]) {
            this.parent[ulp_u] = ulp_v;
            this.size[ulp_v] += this.size[ulp_u];
        } else {
            this.parent[ulp_v] = ulp_u;
            this.size[ulp_u] += this.size[ulp_v];
        }
    }
}
 
function dfs(start, adj, vis) {
    if (vis[start])
        return;
    vis[start] = true;
    for (const it of adj[start]) {
        dfs(it, adj, vis);
    }
}
 
    const n = 6;
    const connections = [
        [0, 1], [0, 2], [0, 3], [1, 2], [1, 3]
    ];
    const adj = new Array(n + 1).fill(null).map(() => []);
    for (const conn of connections) {
        adj[conn[0]].push(conn[1]);
        adj[conn[1]].push(conn[0]);
    }
    const ds = new DisjointSet(n);
    let extra = 0;
    for (const conn of connections) {
        if (ds.findUPar(conn[0]) === ds.findUPar(conn[1]))
            extra++;
        ds.unionBySize(conn[0], conn[1]);
    }
    const vis = new Array(n).fill(false);
    dfs(0, adj, vis);
    let cnt = 0;
    for (let i = 0; i < n; i++) {
        if (!vis[i]) {
            cnt++;
            dfs(i, adj, vis);
        }
    }
    if (cnt <= extra) {
        console.log(cnt);
    } else {
        console.log("All computers cannot be connected");
        console.log(-1);
    }
    // Code and approach contributed by Sanket Gode.


Output

2

Time Complexity: O(n) i.e DFS . The disjoint set function work in almost constant time.
Auxiliary Space: O (V + E). 

Minimize count of connections using Minimum Spanning Tree

The idea is to use a concept similar to that of Minimum Spanning Tree, as in a Graph with N nodes, only N – 1 edges are required to make all the nodes connected.

Redundant edges = Total edges – [(Number of Nodes – 1) – (Number of components – 1)]

If Redundant edges > (Number of components – 1) : It is clear that there are enough wires that can be used to connect disconnected computers.Otherwise, print -1.

Follow the steps below to solve the problem:

  • Initialize an unordered map, say adj to store the adjacency list from the given information about edges.
  • Initialize a vector of boolean datatype, say visited, to store whether a node is visited or not.
  • Generate the adjacency list and also calculate the number of edges.
  • Initialize a variable, say components, to store the count of connected components.
  • Traverse the nodes of the graph using DFS to count the number of connected components and store it in the variable components.
  • Initialize a variable, say redundant, and store the number of redundant edges using the above formula.
  • If redundant edges > components – 1, then the minimum number of required operations is equal to components – 1. Otherwise, print -1.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to visit the nodes of a graph
void DFS(unordered_map<int, vector<int> >& adj, int node,
         vector<bool>& visited)
{
    // If current node is already visited
    if (visited[node])
        return;
 
    // If current node is not visited
    visited[node] = true;
 
    // Recurse for neighbouring nodes
    for (auto x : adj[node]) {
 
        // If the node is not visited
        if (visited[x] == false)
            DFS(adj, x, visited);
    }
}
 
// Utility function to check if it is
// possible to connect all computers or not
int makeConnectedUtil(int N, int connections[][2], int M)
{
    // Stores whether a
    // node is visited or not
    vector<bool> visited(N, false);
 
    // Build the adjacency list
    unordered_map<int, vector<int> > adj;
 
    // Stores count of edges
    int edges = 0;
 
    // Building adjacency list
    // from the given edges
    for (int i = 0; i < M; ++i) {
 
        // Add edges
        adj[connections[i][0]].push_back(connections[i][1]);
        adj[connections[i][1]].push_back(connections[i][0]);
 
        // Increment count of edges
        edges += 1;
    }
 
    // Stores count of components
    int components = 0;
 
    for (int i = 0; i < N; ++i) {
 
        // If node is not visited
        if (visited[i] == false) {
 
            // Increment components
            components += 1;
 
            // Perform DFS
            DFS(adj, i, visited);
        }
    }
 
    // At least N - 1 edges are required
    if (edges < N - 1)
        return -1;
 
    // Count redundant edges
    int redundant = edges - ((N - 1) - (components - 1));
 
    // Check if components can be
    // rearranged using redundant edges
    if (redundant >= (components - 1))
        return components - 1;
 
    return -1;
}
 
// Function to check if it is possible
// to connect all the computers or not
void makeConnected(int N, int connections[][2], int M)
{
    // Stores counmt of minimum
    // operations required
    int minOps = makeConnectedUtil(N, connections, M);
 
    // Print the minimum number
    // of operations required
    cout << minOps;
}
 
// Driver Code
int main()
{
    // Given number of computers
    int N = 4;
 
    // Given set of connections
    int connections[][2] = { { 0, 1 }, { 0, 2 }, { 1, 2 } };
    int M = sizeof(connections) / sizeof(connections[0]);
 
    // Function call to check if it is
    // possible to connect all computers or not
    makeConnected(N, connections, M);
 
    return 0;
}


Java




// Java program for the above approach
import java.io.*;
import java.util.*;
 
class GFG {
 
    // Function to visit the nodes of a graph
    public static void
    DFS(HashMap<Integer, ArrayList<Integer> > adj, int node,
        boolean visited[])
    {
        // If current node is already visited
        if (visited[node])
            return;
 
        // If current node is not visited
        visited[node] = true;
 
        // Recurse for neighbouring nodes
        for (int x : adj.get(node)) {
 
            // If the node is not visited
            if (visited[x] == false)
                DFS(adj, x, visited);
        }
    }
 
    // Utility function to check if it is
    // possible to connect all computers or not
    public static int
    makeConnectedUtil(int N, int connections[][], int M)
    {
        // Stores whether a
        // node is visited or not
        boolean visited[] = new boolean[N];
 
        // Build the adjacency list
        HashMap<Integer, ArrayList<Integer> > adj
            = new HashMap<>();
 
        // Initialize the adjacency list
        for (int i = 0; i < N; i++) {
            adj.put(i, new ArrayList<Integer>());
        }
 
        // Stores count of edges
        int edges = 0;
 
        // Building adjacency list
        // from the given edges
        for (int i = 0; i < M; ++i) {
 
            // Get neighbours list
            ArrayList<Integer> l1
                = adj.get(connections[i][0]);
            ArrayList<Integer> l2
                = adj.get(connections[i][0]);
 
            // Add edges
            l1.add(connections[i][1]);
            l2.add(connections[i][0]);
 
            // Increment count of edges
            edges += 1;
        }
 
        // Stores count of components
        int components = 0;
 
        for (int i = 0; i < N; ++i) {
 
            // If node is not visited
            if (visited[i] == false) {
 
                // Increment components
                components += 1;
 
                // Perform DFS
                DFS(adj, i, visited);
            }
        }
 
        // At least N - 1 edges are required
        if (edges < N - 1)
            return -1;
 
        // Count redundant edges
        int redundant
            = edges - ((N - 1) - (components - 1));
 
        // Check if components can be
        // rearranged using redundant edges
        if (redundant >= (components - 1))
            return components - 1;
 
        return -1;
    }
 
    // Function to check if it is possible
    // to connect all the computers or not
    public static void
    makeConnected(int N, int connections[][], int M)
    {
        // Stores counmt of minimum
        // operations required
        int minOps = makeConnectedUtil(N, connections, M);
 
        // Print the minimum number
        // of operations required
        System.out.println(minOps);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // Given number of computers
        int N = 4;
 
        // Given set of connections
        int connections[][]
            = { { 0, 1 }, { 0, 2 }, { 1, 2 } };
        int M = connections.length;
 
        // Function call to check if it is
        // possible to connect all computers or not
        makeConnected(N, connections, M);
    }
}
 
// This code is contributed by kingash.


Python3




# Python3 code for the above approach
 
# Function to visit the nodes of a graph
 
 
def DFS(adj, node, visited):
 
    # If current node is already visited
    if (visited[node]):
        return
 
    # If current node is not visited
    visited[node] = True
 
    # Recurse for neighbouring nodes
    if(node in adj):
        for x in adj[node]:
 
            # If the node is not visited
            if (visited[x] == False):
                DFS(adj, x, visited)
 
# Utility function to check if it is
# possible to connect all computers or not
 
 
def makeConnectedUtil(N, connections, M):
 
    # Stores whether a
    # node is visited or not
    visited = [False for i in range(N)]
 
    # Build the adjacency list
    adj = {}
 
    # Stores count of edges
    edges = 0
 
    # Building adjacency list
    # from the given edges
    for i in range(M):
 
        # Add edges
        if (connections[i][0] in adj):
            adj[connections[i][0]].append(
                connections[i][1])
        else:
            adj[connections[i][0]] = []
        if (connections[i][1] in adj):
            adj[connections[i][1]].append(
                connections[i][0])
        else:
            adj[connections[i][1]] = []
 
        # Increment count of edges
        edges += 1
 
    # Stores count of components
    components = 0
 
    for i in range(N):
 
        # If node is not visited
        if (visited[i] == False):
 
            # Increment components
            components += 1
 
            # Perform DFS
            DFS(adj, i, visited)
 
    # At least N - 1 edges are required
    if (edges < N - 1):
        return -1
 
    # Count redundant edges
    redundant = edges - ((N - 1) - (components - 1))
 
    # Check if components can be
    # rearranged using redundant edges
    if (redundant >= (components - 1)):
        return components - 1
 
    return -1
 
# Function to check if it is possible
# to connect all the computers or not
 
 
def makeConnected(N, connections, M):
 
    # Stores counmt of minimum
    # operations required
    minOps = makeConnectedUtil(N, connections, M)
 
    # Print the minimum number
    # of operations required
    print(minOps)
 
 
# Driver Code
if __name__ == '__main__':
 
    # Given number of computers
    N = 4
 
    # Given set of connections
    connections = [[0, 1], [0, 2], [1, 2]]
    M = len(connections)
 
    # Function call to check if it is
    # possible to connect all computers or not
    makeConnected(N, connections, M)
 
# This code is contributed by ipg2016107


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG {
 
    // Function to visit the nodes of a graph
    public static void DFS(Dictionary<int, List<int> > adj,
                           int node, bool[] visited)
    {
        // If current node is already visited
        if (visited[node])
            return;
 
        // If current node is not visited
        visited[node] = true;
 
        // Recurse for neighbouring nodes
        foreach(int x in adj[node])
        {
 
            // If the node is not visited
            if (visited[x] == false)
                DFS(adj, x, visited);
        }
    }
 
    // Utility function to check if it is
    // possible to connect all computers or not
    public static int
    makeConnectedUtil(int N, int[, ] connections, int M)
    {
        // Stores whether a
        // node is visited or not
        bool[] visited = new bool[N];
 
        // Build the adjacency list
        Dictionary<int, List<int> > adj
            = new Dictionary<int, List<int> >();
 
        // Initialize the adjacency list
        for (int i = 0; i < N; i++) {
            adj[i] = new List<int>();
        }
 
        // Stores count of edges
        int edges = 0;
 
        // Building adjacency list
        // from the given edges
        for (int i = 0; i < M; ++i) {
 
            // Get neighbours list
            List<int> l1 = adj[connections[i, 0]];
            List<int> l2 = adj[connections[i, 0]];
 
            // Add edges
            l1.Add(connections[i, 1]);
            l2.Add(connections[i, 0]);
 
            // Increment count of edges
            edges += 1;
        }
 
        // Stores count of components
        int components = 0;
 
        for (int i = 0; i < N; ++i) {
 
            // If node is not visited
            if (visited[i] == false) {
 
                // Increment components
                components += 1;
 
                // Perform DFS
                DFS(adj, i, visited);
            }
        }
 
        // At least N - 1 edges are required
        if (edges < N - 1)
            return -1;
 
        // Count redundant edges
        int redundant
            = edges - ((N - 1) - (components - 1));
 
        // Check if components can be
        // rearranged using redundant edges
        if (redundant >= (components - 1))
            return components - 1;
 
        return -1;
    }
 
    // Function to check if it is possible
    // to connect all the computers or not
    public static void
    makeConnected(int N, int[, ] connections, int M)
    {
        // Stores counmt of minimum
        // operations required
        int minOps = makeConnectedUtil(N, connections, M);
 
        // Print the minimum number
        // of operations required
        Console.WriteLine(minOps);
    }
 
    static void Main()
    {
        // Given number of computers
        int N = 4;
 
        // Given set of connections
        int[, ] connections
            = { { 0, 1 }, { 0, 2 }, { 1, 2 } };
        int M = connections.GetLength(0);
 
        // Function call to check if it is
        // possible to connect all computers or not
        makeConnected(N, connections, M);
    }
}
 
// This code is contributed by decode2207.


Javascript




<script>
    // Javascript program for the above approach
     
    // Function to visit the nodes of a graph
    function DFS(adj, node, visited)
    {
        // If current node is already visited
        if (visited[node])
            return;
   
        // If current node is not visited
        visited[node] = true;
   
        // Recurse for neighbouring nodes
        for(let x = 0; x < adj[node].length; x++) {
   
            // If the node is not visited
            if (visited[adj[node][x]] == false)
                DFS(adj, adj[node][x], visited);
        }
    }
   
    // Utility function to check if it is
    // possible to connect all computers or not
    function makeConnectedUtil(N, connections, M)
    {
        // Stores whether a
        // node is visited or not
        let visited = new Array(N);
        visited.fill(false);
   
        // Build the adjacency list
        let adj = new Map();
   
        // Initialize the adjacency list
        for (let i = 0; i < N; i++) {
            adj[i] = [];
        }
   
        // Stores count of edges
        let edges = 0;
   
        // Building adjacency list
        // from the given edges
        for (let i = 0; i < M; ++i) {
   
            // Get neighbours list
            let l1 = adj[connections[i][0]];
            let l2 = adj[connections[i][0]];
   
            // Add edges
            l1.push(connections[i][1]);
            l2.push(connections[i][0]);
   
            // Increment count of edges
            edges += 1;
        }
   
        // Stores count of components
        let components = 0;
   
        for (let i = 0; i < N; ++i) {
   
            // If node is not visited
            if (visited[i] == false) {
   
                // Increment components
                components += 1;
   
                // Perform DFS
                DFS(adj, i, visited);
            }
        }
   
        // At least N - 1 edges are required
        if (edges < N - 1)
            return -1;
   
        // Count redundant edges
        let redundant = edges - ((N - 1) - (components - 1));
   
        // Check if components can be
        // rearranged using redundant edges
        if (redundant >= (components - 1))
            return components - 1;
   
        return -1;
    }
   
    // Function to check if it is possible
    // to connect all the computers or not
    function makeConnected(N, connections, M)
    {
        // Stores counmt of minimum
        // operations required
        let minOps = makeConnectedUtil(N, connections, M);
   
        // Print the minimum number
        // of operations required
        document.write(minOps);
    }
     
    // Given number of computers
    let N = 4;
  
    // Given set of connections
    let connections = [ [0, 1], [0, 2], [1, 2] ];
    let M = connections.length;
  
    // Function call to check if it is
    // possible to connect all computers or not
    makeConnected(N, connections, M);
  
 // This code is contributed by sureh07.
</script>


Output

1

Time Complexity: O(N + M)
Auxiliary Space: O(N)



Last Updated : 01 Sep, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads