Open In App

Check if given graph is connected or not after removal of ith node sequential

Last Updated : 24 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given an undirected graph with N nodes, M edges given by array edges[][2] and permutation array A[] of size N which indicates the order in which each and every node of graph will be removed. The task is to find if graph is connected or not after removal of ith node sequential from given array A[]. Graph is connected if it is possible to traverse from any node to any other node. Print “YES” if graph is connected else print “NO”.

Note: Removal of node is permanent from the given undirected graph.

Examples:

Input: N = 4, edges[][2] = { {1, 2}, {2, 3}, {3, 4} }, A[] = {3, 4, 1, 2}
Output: NO YES YES YES
Explanation:

  • Removing node A[1] = 3, after removal as there is no path to travel between 1 and 4 hence “NO” is answer.
  • Removing node A[2] = 4, after removal graph becomes connected hence “YES” is answer
  • Removing node A[3] = 1, after removal graph is still connected since it has only one node left hence “YES” is answer
  • Removing node A[4] = 2, after removal graph has no nodes hence “YES” is answer

Input: N = 5, edges[][2] = { {1, 2}, {1, 3}, {3, 5}, {2, 5}, {5, 4} }, A[] = {3, 5, 2, 4, 1}
Output: YES NO NO YES YES
Explanation:

  • Removing node A[1] = 3, after removal as whole graph is still connected hence “YES” is answer
  • Removing node A[2] = 5, after removal as there is no path to travel between 1 and 4 hence “NO” is answer
  • Removing node A[3] = 2, after removal as there is still no path to travel between 1 and 4 hence “NO” is answer
  • Removing node A[4] = 4, after removal as there is only one node left hence “YES” is answer
  • Removing node A[5] = 1, after removal graph has no nodes hence “YES” is answer.

Approach: The problem can be solved using the following approach:

Disjoint Set can be used to solve this problem. Rather than deleting from first node to last node and run a DFS for every node to check whether the graph is connected, we can start from the last node and keep inserting the nodes and keeping the count of nodes in each connected component.

Rather than deleting in A[0] -> A[1] -> A[2] -> …… ->A[N – 1] this order

Let’s insert in A[N – 1] -> A[N – 2] -> A[N – 3] ……. -> A[0] this order

Insertion operation will be made using union() function of DSU and before each insertion we will check whether given graph is connected or not by finding component size in which the current node belongs. If the size is equal to number of elements inserted, then graph is connected otherwise it is disconnected.

Below are the steps for the above approach:

  • Define a struct DSU of size N + 1 along with the required methods.
  • Declare isInserted[] array which keep tracks whether current element is inserted or not.
  • Declare variable firstNodeToBeInserted with value A[N – 1] (which stores first node that we will insert in our graph).
  • Declare array of strings ans[].
  • Iterate i from N – 1 to 0 to follow given steps:
    • if dsu.size() of firstNodeToBeInserted is equal to N – i – 1, then push string “YES” in array of strings ans[].
    • Otherwise push string “NO” in array of string ans[].
    • Mark current node 1 in isInserted[] array.
    • Iterate on adjacent elements of node V as U and if adjacent node U is already inserted in graph, then connect components containing nodes V and U using dsu.union() function.
  • Return the reverse of ans[].

Below is the implementation of the above approach:

C++




// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// to avoid integer overflow
#define int long long
 
// Structure for Disjoint set union Data structure
struct DSU {
 
    // Declaring array
    vector<int> parent;
 
    // initializing every nodes parent to be -1 initially
    DSU(int N) { parent = vector<int>(N + 1, -1); }
 
    // get parent for x
    int get(int x)
    {
        return parent[x] < 0 ? x
                             : parent[x] = get(parent[x]);
    }
 
    // function to check whether node a and node b
    // belongs to same component or not
    bool same_set(int a, int b) { return get(a) == get(b); }
 
    // check size of component that node x belongs to
    int size(int x) { return -parent[get(x)]; }
 
    // connect component containing x and y (make them same
    // component)
    bool _union(int x, int y)
    {
 
        // get parents of x and y
        x = get(x), y = get(y);
 
        // if x and y are same nodes return false;
        if (x == y)
            return false;
 
        // if parent of x is greater than parent of y swap x
        // and y
        if (parent[x] > parent[y])
            swap(x, y);
 
        // add all nodes of y to x
        parent[x] += parent[y];
 
        // parent of y ix x
        parent[y] = x;
 
        // return true to end the function
        return true;
    }
};
 
// Check if given graph is connected or not
// after removal of i'th node
void isGraphConnected(int N, int edges[][2], int M, int A[])
{
    // Initializing Disjoing Union data structure
    DSU dsu(N + 1);
 
    // Declare adjacency list
    vector<vector<int> > adj(N + 1);
 
    // fill the adjacency list
    for (int i = 0; i < M; i++) {
 
        // there is undirected edge from edges[i][0] to
        // edges[i][1]
        adj[edges[i][0]].push_back(edges[i][1]);
        adj[edges[i][1]].push_back(edges[i][0]);
    }
 
    // visited array so we will keep inserting all nodes
    vector<int> isInserted(N + 1, 0);
 
    // previous node
    int firstNodeToBeInserted = A[N - 1];
 
    // storing answer in ans variable
    vector<string> ans;
 
    // start inserting nodes from backwards
    for (int i = N - 1; i >= 0; i--) {
 
        // if number of nodes in component of first node
        // that was inserted in this case A[N - 1] have size
        // equal to number of total nodes inserted till now
        // then graph is connected or if there are no nodes
        // inserted then also graph is connected since graph
        // will be empty graph
        if (dsu.size(firstNodeToBeInserted) == (N - 1 - i)
            or i == N - 1)
            ans.push_back("YES");
 
        // otherwise
        else
            ans.push_back("NO");
 
        // current node to be inserted
        int V = A[i];
 
        // marking current node as true which signifies
        // current node is inserted in graph
        isInserted[V] = 1;
 
        // iterating over adjacents V which are inserted
        for (auto& U : adj[V]) {
            if (isInserted[U])
                dsu._union(V, U);
        }
    }
 
    // reverse the ans so insertion from last to first node
    // becomes deletion from first node to last node
    reverse(ans.begin(), ans.end());
 
    // print answer whether given graph is connected after
    // deletion of i'th node
    for (int i = 0; i < N; i++) {
        cout << ans[i] << " ";
    }
    cout << endl;
}
 
// Driver Code
int32_t main()
{
    // Input
    int N = 5, M = 5;
    int edges[][2] = { { 1, 2 }, { 1, 3 }, { 3, 5 }, {2, 5}, {5, 4} };
    int A[] = {3, 5, 2, 4, 1};
 
    // Function Call
    isGraphConnected(N, edges, M, A);
   
    return 0;
}


Java




// Java program for the above approach
import java.util.*;
 
// Class for Disjoint set union Data structure
class DSU {
    // Declaring array
    private int[] parent;
 
    // initializing every node's parent to be -1 initially
    public DSU(int N)
    {
        parent = new int[N + 1];
        Arrays.fill(parent, -1);
    }
 
    // get parent for x
    public int get(int x)
    {
        return parent[x] < 0 ? x
                             : (parent[x] = get(parent[x]));
    }
 
    // function to check whether node a and node b
    // belong to the same component or not
    public boolean sameSet(int a, int b)
    {
        return get(a) == get(b);
    }
 
    // check the size of the component that node x belongs
    // to
    public int size(int x) { return -parent[get(x)]; }
 
    // connect the component containing x and y (make them
    // the same component)
    public boolean union(int x, int y)
    {
        // get parents of x and y
        x = get(x);
        y = get(y);
 
        // if x and y are the same nodes return false;
        if (x == y)
            return false;
 
        // if the parent of x is greater than the parent of
        // y swap x and y
        if (parent[x] > parent[y]) {
            int temp = x;
            x = y;
            y = temp;
        }
 
        // add all nodes of y to x
        parent[x] += parent[y];
 
        // parent of y is x
        parent[y] = x;
        return true;
    }
}
 
public class GFG {
    public static void main(String[] args)
    {
        int N = 5, M = 5;
        int[][] edges = {
            { 1, 2 }, { 1, 3 }, { 3, 5 }, { 2, 5 }, { 5, 4 }
        };
        int[] A = { 3, 5, 2, 4, 1 };
 
        isGraphConnected(N, edges, M, A);
    }
 
    // Check if the given graph is connected or not
    // after the removal of the i'th node
    public static void
    isGraphConnected(int N, int[][] edges, int M, int[] A)
    {
        // Initializing Disjoint Union data structure
        DSU dsu = new DSU(N + 1);
 
        // Declare adjacency list
        List<List<Integer> > adj = new ArrayList<>(N + 1);
 
        // fill the adjacency list
        for (int i = 0; i <= N; i++) {
            adj.add(new ArrayList<>());
        }
 
        // Construct adjacency list
        for (int i = 0; i < M; i++) {
            int u = edges[i][0];
            int v = edges[i][1];
            adj.get(u).add(v);
            adj.get(v).add(u);
        }
 
        boolean[] isInserted = new boolean[N + 1];
        int firstNodeToBeInserted = A[N - 1];
        List<String> ans = new ArrayList<>();
 
        // Start inserting nodes from backwards
        for (int i = N - 1; i >= 0; i--) {
            // If the size of the component containing the
            // first node inserted (A[N-1]) is equal to the
            // number of total nodes inserted till now
            // (N-1-i), or if there are no nodes inserted
            // yet (i == N-1), then the graph is connected
            if (dsu.size(firstNodeToBeInserted)
                    == (N - 1 - i)
                || i == N - 1) {
                ans.add("YES");
            }
            else {
                ans.add("NO");
            }
 
            int V = A[i];
            isInserted[V] = true;
 
            // Iterate over adjacent nodes of V that have
            // been inserted
            for (int U : adj.get(V)) {
                if (isInserted[U]) {
                    dsu.union(V, U);
                }
            }
        }
 
        Collections.reverse(ans);
 
        // Print whether the given graph is connected after
        // the deletion of the i-th node
        for (String s : ans) {
            System.out.print(s + " ");
        }
        System.out.println();
    }
}
 
// This code is contributed by Susobhan Akhuli


Python3




class DSU:
    def __init__(self, N):
        self.parent = [-1] * (N + 1)
 
    def get(self, x):
        return x if self.parent[x] < 0 else self.get(self.parent[x])
 
    def same_set(self, a, b):
        return self.get(a) == self.get(b)
 
    def size(self, x):
        return -self.parent[self.get(x)]
 
    def _union(self, x, y):
        x, y = self.get(x), self.get(y)
 
        if x == y:
            return False
 
        if self.parent[x] > self.parent[y]:
            x, y = y, x
 
        self.parent[x] += self.parent[y]
        self.parent[y] = x
 
        return True
 
 
def is_graph_connected(N, edges, M, A):
    dsu = DSU(N + 1)
    adj = [[] for _ in range(N + 1)]
 
    for edge in edges:
        adj[edge[0]].append(edge[1])
        adj[edge[1]].append(edge[0])
 
    is_inserted = [0] * (N + 1)
    first_node_to_be_inserted = A[N - 1]
    ans = []
 
    for i in range(N - 1, -1, -1):
        if dsu.size(first_node_to_be_inserted) == (N - 1 - i) or i == N - 1:
            ans.append("YES")
        else:
            ans.append("NO")
 
        V = A[i]
        is_inserted[V] = 1
 
        for U in adj[V]:
            if is_inserted[U]:
                dsu._union(V, U)
 
    ans.reverse()
 
    for i in range(N):
        print(ans[i], end=" ")
 
    print()
 
 
# Driver Code
if __name__ == "__main__":
    # Input
    N, M = 5, 5
    edges = [[1, 2], [1, 3], [3, 5], [2, 5], [5, 4]]
    A = [3, 5, 2, 4, 1]
 
    # Function Call
    is_graph_connected(N, edges, M, A)


C#




using System;
using System.Collections.Generic;
 
public class DSU
{
    // Declaring array
    private List<int> parent;
 
    // initializing every nodes parent to be -1 initially
    public DSU(int N)
    {
        parent = new List<int>(N + 1);
        for (int i = 0; i <= N; i++)
        {
            parent.Add(-1);
        }
    }
 
    // get parent for x
    public int Get(int x)
    {
        return parent[x] < 0 ? x : parent[x] = Get(parent[x]);
    }
 
    // function to check whether node a and node b
    // belongs to same component or not
    public bool SameSet(int a, int b)
    {
        return Get(a) == Get(b);
    }
 
    // check size of component that node x belongs to
    public int Size(int x)
    {
        return -parent[Get(x)];
    }
 
    // connect component containing x and y (make them same
    // component)
    public bool Union(int x, int y)
    {
        // get parents of x and y
        x = Get(x);
        y = Get(y);
 
        // if x and y are same nodes return false;
        if (x == y)
            return false;
 
        // if parent of x is greater than parent of y swap x
        // and y
        if (parent[x] > parent[y])
        {
            int temp = x;
            x = y;
            y = temp;
        }
 
        // add all nodes of y to x
        parent[x] += parent[y];
 
        // parent of y is x
        parent[y] = x;
 
        // return true to end the function
        return true;
    }
}
 
public class Graph
{
    // Check if given graph is connected or not
    // after removal of i'th node
    public static void IsGraphConnected(int N, int[,] edges, int M, int[] A)
    {
        // Initializing Disjoing Union data structure
        DSU dsu = new DSU(N + 1);
 
        // Declare adjacency list
        List<List<int>> adj = new List<List<int>>(N + 1);
 
        // fill the adjacency list
        for (int i = 0; i < N + 1; i++)
        {
            adj.Add(new List<int>());
        }
 
        for (int i = 0; i < M; i++)
        {
            // there is undirected edge from edges[i, 0] to
            // edges[i, 1]
            adj[edges[i, 0]].Add(edges[i, 1]);
            adj[edges[i, 1]].Add(edges[i, 0]);
        }
 
        // visited array so we will keep inserting all nodes
        List<int> isInserted = new List<int>(N + 1);
        for (int i = 0; i <= N; i++)
        {
            isInserted.Add(0);
        }
 
        // previous node
        int firstNodeToBeInserted = A[N - 1];
 
        // storing answer in ans variable
        List<string> ans = new List<string>();
 
        // start inserting nodes from backwards
        for (int i = N - 1; i >= 0; i--)
        {
            // if number of nodes in component of first node
            // that was inserted in this case A[N - 1] have size
            // equal to number of total nodes inserted till now
            // then graph is connected or if there are no nodes
            // inserted then also graph is connected since graph
            // will be empty graph
            if (dsu.Size(firstNodeToBeInserted) == (N - 1 - i)
                || i == N - 1)
                ans.Add("YES");
 
            // otherwise
            else
                ans.Add("NO");
 
            // current node to be inserted
            int V = A[i];
 
            // marking current node as true which signifies
            // current node is inserted in graph
            isInserted[V] = 1;
 
            // iterating over adjacents V which are inserted
            foreach (var U in adj[V])
            {
                if (isInserted[U] == 1)
                    dsu.Union(V, U);
            }
        }
 
        // reverse the ans so insertion from last to first node
        // becomes deletion from first node to last node
        ans.Reverse();
 
        // print answer whether given graph is connected after
        // deletion of i'th node
        foreach (var item in ans)
        {
            Console.Write(item + " ");
        }
        Console.WriteLine();
    }
}
 
public class Program
{
    // Driver Code
    public static void Main(string[] args)
    {
        // Input
        int N = 5, M = 5;
        int[,] edges = { { 1, 2 }, { 1, 3 }, { 3, 5 }, { 2, 5 }, { 5, 4 } };
        int[] A = { 3, 5, 2, 4, 1 };
 
        // Function Call
        Graph.IsGraphConnected(N, edges, M, A);
    }
}


Javascript




// Javascript program for the above approach
// Define a class for Disjoint Set Union
class DSU {
    constructor(N) {
        // Initializing parent array with -1
        this.parent = Array(N + 1).fill(-1);
    }
 
    // Function to get the parent of a node
    get(x) {
        return this.parent[x] < 0 ? x : (this.parent[x] = this.get(this.parent[x]));
    }
 
    // Function to check if two nodes belong to the same component
    sameSet(a, b) {
        return this.get(a) === this.get(b);
    }
 
    // Function to get the size of the component containing a node
    size(x) {
        return -this.parent[this.get(x)];
    }
 
    // Function to merge two components
    union(x, y) {
        x = this.get(x);
        y = this.get(y);
        if (x === y) return false;
        if (this.parent[x] > this.parent[y]) [x, y] = [y, x];
        this.parent[x] += this.parent[y];
        this.parent[y] = x;
        return true;
    }
}
 
// Function to check if the graph is connected after removing the i'th node
function isGraphConnected(N, edges, M, A) {
    // Initialize the DSU
    const dsu = new DSU(N + 1);
 
    // Initialize adjacency list
    const adj = Array.from({ length: N + 1 }, () => []);
 
    // Fill the adjacency list
    edges.forEach(([u, v]) => {
        adj[u].push(v);
        adj[v].push(u);
    });
 
    // Store answers
    const ans = [];
 
    // Mark inserted nodes
    const isInserted = Array(N + 1).fill(false);
 
    // Start from the last node to be inserted
    let firstNodeToBeInserted = A[N - 1];
 
    for (let i = N - 1; i >= 0; i--) {
        if (dsu.size(firstNodeToBeInserted) === (N - 1 - i) || i === N - 1) {
            ans.push("YES");
        } else {
            ans.push("NO");
        }
 
        let V = A[i];
        isInserted[V] = true;
 
        for (let U of adj[V]) {
            if (isInserted[U]) dsu.union(V, U);
        }
    }
 
    // Reverse the answers
    ans.reverse();
 
    // Print the results
    console.log(ans.join(" "));
}
 
// Driver Code
(() => {
    // Input
    const N = 5;
    const M = 5;
    const edges = [[1, 2], [1, 3], [3, 5], [2, 5], [5, 4]];
    const A = [3, 5, 2, 4, 1];
 
    // Function Call
    isGraphConnected(N, edges, M, A);
})();
 
// This code is contributed by Susobhan Akhuli


Output

YES NO NO YES YES 





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



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads