Check if given graph is connected or not after removal of ith node sequential
Last Updated :
24 Feb, 2024
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
Time Complexity: O(N), where N is the number of nodes in the input graph.
Auxiliary Space: O(N)
Similar Reads
Check if a given Graph is 2-edge connected or not
Given an undirected graph G, with V vertices and E edges, the task is to check whether the graph is 2-edge connected or not. A graph is said to be 2-edge connected if, on removing any edge of the graph, it still remains connected, i.e. it contains no Bridges. Examples: Input: V = 7, E = 9 Output: Ye
12 min read
Count of connected components in given graph after removal of given Q vertices
Given an undirected graph g, the task is to find the number of coalitions formed in it after the removal of Q vertices and maximum vertices among all these connected components. A coalition is defined as the number of connected components left after removal of Q vertices i.e vertices being removed f
10 min read
Check if a given tree graph is linear or not
Given a tree check if it is linear or not. 1 / \ 2 3 Linear as we can form a line 2 1 3 1 / \ 2 3 / \ 4 5 Not linear Examples: Input : 3 1 2 1 3 Output : YES Explanation: The Tree formed is 2-1-3 which is a linear one. Input : 4 1 2 2 3 4 2 Output : NO Approach: The given tree would be linear only i
6 min read
Check if a directed graph is connected or not
Given a directed graph. The task is to check if the given graph is connected or not.Examples: Input: Output: YesInput: Output: No Approach: Take two bool arrays vis1 and vis2 of size N (number of nodes of a graph) and keep false in all indexes.Start at a random vertex v of the graph G, and run a DFS
7 min read
Check if a given graph is tree or not
Write a function that returns true if a given undirected graph is a tree and false otherwise. For example, the following graph is a tree. But the following graph is not a tree. Approach 1: An undirected graph is a tree if it has the following properties. There is no cycle. The graph is connected. Fo
15+ min read
Check if removing a given edge disconnects a graph
Given a graph withâ¯Vâ¯vertices andâ¯Eâ¯edges, along with a specific edge connecting verticesâ¯câ¯and d, the task is to determine whether this edge is a bridge. An edge (câd) is said to be a bridge if removing it results in an increase in the number of connected components â meaning that verticesâ¯câ¯andâ¯d
8 min read
Check if a given directed graph is strongly connected | Set 2 (Kosaraju using BFS)
Given a directed graph, find out whether the graph is strongly connected or not. A directed graph is strongly connected if there is a path between any two pairs of vertices. There are different methods to check the connectivity of directed graph but one of the optimized method is Kosarajuâs DFS base
14 min read
Check if a graph is strongly connected | Set 1 (Kosaraju using DFS)
Given a directed graph, find out whether the graph is strongly connected or not. A directed graph is strongly connected if there is a path between any two pair of vertices. For example, following is a strongly connected graph. It is easy for undirected graph, we can just do a BFS and DFS starting fr
13 min read
Check if every vertex triplet in graph contains two vertices connected to third vertex
Given an undirected graph with N vertices and K edges, the task is to check if for every combination of three vertices in the graph, there exists two vertices which are connected to third vertex. In other words, for every vertex triplet (a, b, c), if there exists a path between a and c, then there s
9 min read
Check if incoming edges in a vertex of directed graph is equal to vertex itself or not
Given a directed Graph G(V, E) with V vertices and E edges, the task is to check that for all vertices of the given graph, the incoming edges in a vertex is equal to the vertex itself or not. Examples: Input: Output: Yes Explanation: For vertex 0 there are 0 incoming edges, for vertex 1 there is 1 i
6 min read