Open In App

Count of nodes accessible from all other nodes of Graph

Last Updated : 30 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a directed graph with N nodes and M edges in array V[], the task is to find the number of nodes that are accessible from all other nodes i.e., they have at least one path from all other nodes.

Examples:

Input: N = 5 and M = 5, V = [[1, 2], [2, 3], [3, 4], [4, 3], [5, 4]]
Output: 2
Explanation:
We can look closely after forming graph 
than captain america only can hide in a 
room 3 and 4 because they are the only room 
which have gates through them. So, 
answer is 2.

Input: N = 2, M = 1, V = [[1, 2]]
Output: 1

 

Approach: This problem can be solved using Kosaraju’s Algorithm to find the count of Strongly Connected Components based on the following idea:

All the nodes in a single strongly connected component are reachable from any other node of that component. If each connected component is considered as a node of the graph then there are the following cases:

  • The connected components are disconnected. So, more than one component will have outdegree greater than 0. In this case, no node is reachable from all other nodes.
  • There is only one connected component. This time all the nodes are reachable from all other nodes.
  • There are more than one connected components and only one node has outdegree equal to 0. In this case only that node is reachable from all other nodes. 

Follow the steps mentioned below to implement the above idea:

  • Find all strongly connected components of the given graph
  • Create a new graph in which each strongly connected component is considered as a single node. (let’s say this graph is grrrr)
  • Find number of nodes in grrrr having outdegree ==0 (let this number is x1)
    • If x1 > 1 then answer is 0 because this suggests that some nodes are not reachable from others or some components are disconnected.
    • If x1 = 0 then answer is also 0.
    • So  exist only when x1 = 1 and the answer is equal to the number of nodes in the strongly connected component having outdegree = 0 in graph grrrr.

Below is the implementation of the above approach.

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
vector<int> adj[100001];
vector<int> transpose[100001];
int vis[100001], parent[100001], no[100001];
 
// Function to form the components
void dfs(int node, vector<int> adj[], stack<int>& st,
         int vis[])
{
    vis[node] = 1;
    for (int it : adj[node]) {
        if (vis[it] == 0) {
            dfs(it, adj, st, vis);
        }
    }
    st.push(node);
}
 
// Function to run dfs in the
// transpose adjacency to get
// the strongly connected components
void dfs_(int node, vector<int> transpose[], int vis[],
          int par)
{
    vis[node] = 1;
    parent[node] = par;
    no[par]++;
    for (int it : transpose[node]) {
        if (vis[it] == 0) {
            dfs_(it, transpose, vis, par);
        }
    }
}
 
// Function to form the new graph using
// the strongly connected components
void dfs__(int node, int vis[], vector<int> adj[],
           vector<int> adjn[], int parent[])
{
    vis[node] = 1;
    for (int it : adj[node]) {
        int par1 = parent[node];
        int par2 = parent[it];
        if (par1 == par2) {
            continue;
        }
        adjn[par1].push_back(par2);
        if (vis[it] == 0) {
            dfs__(it, vis, adj, adjn, parent);
        }
    }
}
 
// Function to find the total number
// of reachable nodes
int countReachables(int N, int M, vector<pair<int, int> > V)
{
    for (int i = 0; i < M; i++) {
        adj[V[i].first - 1].push_back(V[i].second - 1);
    }
    memset(vis, 0, sizeof(vis));
 
    // Stack to store the components
    stack<int> st;
    for (int i = 0; i < N; i++) {
        if (vis[i] == 0) {
            dfs(i, adj, st, vis);
        }
    }
 
    // Transpose the graph and perform the second DFS
    // traversal
    for (int i = 0; i < N; i++) {
        for (int it : adj[i]) {
            transpose[it].push_back(i);
        }
    }
    memset(vis, 0, sizeof(vis));
    memset(parent, 0, sizeof(parent));
    memset(no, 0, sizeof(no));
    int par = 0;
    while (!st.empty()) {
        int node = st.top();
        st.pop();
        if (vis[node] == 0) {
            dfs_(node, transpose, vis, par);
            par++;
        }
    }
 
    // Adjacency matrix to represent the graph
    // where each node is a strongly connected component
    vector<int> adjn[100001];
    memset(vis, 0, sizeof(vis));
    for (int i = 0; i < N; i++) {
        if (vis[i] == 0) {
            dfs__(i, vis, adj, adjn, parent);
        }
    }
    // Check nodes with outdegree 0
    int outDegree = 0;
    for (int i = 0; i < par; i++) {
        if (adjn[i].size() == 0) {
            outDegree++;
        }
    }
 
    // Decide the count based on the conditions
    if (outDegree > 1 || outDegree == 0) {
        return 0;
    }
    else {
        for (int i = 0; i < par; i++) {
            if (adjn[i].size() == 0) {
                return no[i];
            }
        }
        return 0;
    }
}
// Driver code
int main()
{
    int N = 5;
    int M = 5;
    int V[M + 1][2] = {
        { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 3 }, { 5, 4 }
    };
 
    vector<pair<int, int> > V_vec;
    for (int i = 0; i < M; i++) {
        V_vec.push_back(make_pair(V[i][0], V[i][1]));
    }
    // Function call
    int ans = countReachables(N, M, V_vec);
    cout << ans;
    return 0;
}


Java




// Java code to implement the approach
 
import java.io.*;
import java.util.*;
 
class GFG {
 
    // Function to form the components
    private static void
    dfs(int node, ArrayList<ArrayList<Integer> > adj,
        Stack<Integer> st, int[] vis)
    {
        vis[node] = 1;
        for (Integer it : adj.get(node)) {
            if (vis[it] == 0) {
                dfs(it, adj, st, vis);
            }
        }
        st.push(node);
    }
 
    // Function to run dfs in the
    // transpose adjacency to get
    // the strongly connected components
    private static void
    dfs_(int node, ArrayList<ArrayList<Integer> > transpose,
         int[] vis, int par, int[] parent, int[] no)
    {
        vis[node] = 1;
 
        parent[node] = par;
        no[par]++;
        for (Integer it : transpose.get(node)) {
            if (vis[it] == 0) {
                dfs_(it, transpose, vis, par, parent, no);
            }
        }
    }
 
    // Function to form the new graph using
    // the strongly connected components
    private static void
    dfs__(int node, int[] vis,
          ArrayList<ArrayList<Integer> > adj,
          ArrayList<ArrayList<Integer> > adjn, int[] parent)
    {
        vis[node] = 1;
        for (Integer it : adj.get(node)) {
            int par1 = parent[node];
            int par2 = parent[it];
            if (par1 == par2) {
                continue;
            }
            adjn.get(par1).add(par2);
            if (vis[it] == 0) {
                dfs__(it, vis, adj, adjn, parent);
            }
        }
    }
 
    // Function to find the total number
    // of reachable nodes
    public static int countReachables(int N, int M,
                                      int V[][])
    {
        ArrayList<ArrayList<Integer> > adj
            = new ArrayList<>();
        for (int i = 0; i < N; i++) {
            adj.add(new ArrayList<>());
        }
 
        // Generate the adjacency matrix
        for (int i = 0; i < M; i++) {
            adj.get(V[i][0] - 1).add(V[i][1] - 1);
        }
        int[] vis = new int[N];
 
        // Stack to store the components
        Stack<Integer> st = new Stack<>();
        for (int i = 0; i < N; i++) {
            if (vis[i] == 0) {
                dfs(i, adj, st, vis);
            }
        }
        ArrayList<ArrayList<Integer> > transpose
            = new ArrayList<>();
        for (int i = 0; i < N; i++) {
            transpose.add(new ArrayList<>());
            vis[i] = 0;
        }
 
        // Transpose adjacency matrix
        for (int i = 0; i < M; i++) {
            transpose.get(V[i][1] - 1).add(V[i][0] - 1);
        }
        int[] parent = new int[N];
        int par = 0;
        int[] no = new int[N];
        while (!st.isEmpty()) {
            int node = st.pop();
            if (vis[node] == 0) {
                dfs_(node, transpose, vis, par, parent, no);
                par++;
            }
        }
 
        // Adjacency matrix to represent the graph
        // where each node is a strongly connected component
        ArrayList<ArrayList<Integer> > adjn
            = new ArrayList<>();
        for (int i = 0; i < par; i++) {
            adjn.add(new ArrayList<>());
        }
        Arrays.fill(vis, 0);
        for (int i = 0; i < N; i++) {
            if (vis[i] == 0) {
                dfs__(i, vis, adj, adjn, parent);
            }
        }
 
        // Check nodes with outdegree 0
        int outDegree = 0;
        for (int i = 0; i < par; i++) {
            if (adjn.get(i).size() == 0) {
                outDegree++;
            }
        }
 
        // Decide the count based on the conditions
        if (outDegree > 1 || outDegree == 0) {
            return 0;
        }
        else {
            for (int i = 0; i < par; i++) {
                if (adjn.get(i).size() == 0) {
                    return no[i];
                }
            }
        }
        return -1;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int N = 5;
        int M = 5;
        int V[][] = new int[M + 1][2];
 
        V[0][0] = 1;
        V[0][1] = 2;
        V[1][0] = 2;
        V[1][1] = 3;
        V[2][0] = 3;
        V[2][1] = 4;
        V[3][0] = 4;
        V[3][1] = 3;
        V[4][0] = 5;
        V[4][1] = 4;
 
        // Function call
        int ans = countReachables(N, M, V);
        System.out.println(ans);
    }
}


Python3




from collections import defaultdict
from typing import List, Tuple
 
def countReachables(N: int, M: int, V: List[Tuple[int, int]]) -> int:
  # First DFS traversal
  # Create an adjacency list representation of the graph
  # Visit all nodes and push the node to the stack when all its children have been visited
    def dfs(node: int, adj: List[List[int]], st: list, vis: List[int]):
        vis[node] = 1
        for it in adj[node]:
            if vis[it] == 0:
                dfs(it, adj, st, vis)
        st.append(node)
         
  # Second DFS traversal
  # Transpose the graph and visit all the nodes in the order they were pushed to the stack in the first DFS traversal
  # Record the number of nodes in each strongly connected component
  # Record the parent of each node in the DFS tree
    def dfs_(node: int, transpose: List[List[int]], vis: List[int], par: int, parent: List[int], no: List[int]):
        vis[node] = 1
        parent[node] = par
        no[par] += 1
        for it in transpose[node]:
            if vis[it] == 0:
                dfs_(it, transpose, vis, par, parent, no)
  # Third DFS traversal
  # Create a new graph that represents the strongly connected components
  # Visit all the nodes in the original graph in the order they were pushed to the stack in the first DFS traversal
  # If two nodes are in the same strongly connected component, skip them
  # If two nodes are in different strongly connected components, add an edge from the component of the first node to the component of the second node
    def dfs__(node: int, vis: List[int], adj: List[List[int]], adjn: List[List[int]], parent: List[int]):
        vis[node] = 1
        for it in adj[node]:
            par1 = parent[node]
            par2 = parent[it]
            if par1 == par2:
                continue
            adjn[par1].append(par2)
            if vis[it] == 0:
                dfs__(it, vis, adj, adjn, parent)
                 
   # Convert the list of edges to an adjacency list
    adj = defaultdict(list)
    for i in range(M):
        adj[V[i][0]-1].append(V[i][1]-1)
    vis = [0] * N
 
    st = []
    for i in range(N):
        if vis[i] == 0:
            dfs(i, adj, st, vis)
             
    # Transpose the graph and perform the second DFS traversal
    transpose = defaultdict(list)
    for i in range(N):
        transpose[V[i][1]-1].append(V[i][0]-1)
    vis = [0] * N
    parent = [0] * N
    par = 0
    no = [0] * N
    while st:
        node = st.pop()
        if vis[node] == 0:
            dfs_(node, transpose, vis, par, parent, no)
            par += 1
             
    # Create a new graph
    adjn = defaultdict(list)
    vis = [0] * N
    for i in range(N):
        if vis[i] == 0:
            dfs__(i, vis, adj, adjn, parent)
     
    outDegree = 0
    for i in range(par):
        if len(adjn[i]) == 0:
            outDegree += 1
    if outDegree > 1 or outDegree == 0:
        return 0
    else:
        for i in range(par):
            if len(adjn[i]) == 0:
                return no[i]
        return 0
 
if __name__ == "__main__":
    N = 5
    M = 5
    V = [[1, 2], [2, 3], [3, 4], [4, 3], [5, 4]]
 
    # Function call
    ans = countReachables(N, M, V)
    print(ans)


C#




using System;
using System.Collections.Generic;
 
class GFG
{
    static List<int>[] adj = new List<int>[100001];
    static List<int>[] transpose = new List<int>[100001];
    static int[] vis = new int[100001];
    static int[] parent = new int[100001];
    static int[] no = new int[100001];
    // Function to form the components
    static void DFS(int node, List<int>[] graph, Stack<int> st, int[] visited)
    {
        visited[node] = 1;
        foreach (var neighbor in graph[node])
        {
            if (visited[neighbor] == 0)
            {
                DFS(neighbor, graph, st, visited);
            }
        }
        st.Push(node);
    }
    // Function to run DFS in the transpose adjacency to
  // get the strongly connected components
    static void DFS_(int node, List<int>[] graph, int[] visited, int par)
    {
        visited[node] = 1;
        parent[node] = par;
        no[par]++;
        foreach (var neighbor in graph[node])
        {
            if (visited[neighbor] == 0)
            {
                DFS_(neighbor, graph, visited, par);
            }
        }
    }
    // Function to form the new graph using strongly connected components
    static void DFS__(int node, int[] visited, List<int>[] graph, List<int>[] newGraph, int[] parents)
    {
        visited[node] = 1;
        foreach (var neighbor in graph[node])
        {
            int par1 = parents[node];
            int par2 = parents[neighbor];
            if (par1 == par2)
            {
                continue;
            }
            newGraph[par1].Add(par2);
            if (visited[neighbor] == 0)
            {
                DFS__(neighbor, visited, graph, newGraph, parents);
            }
        }
    }
    // Function to find the total number of the reachable nodes
    static int CountReachables(int N, int M, List<Tuple<int, int>> edges)
    {
        for (int i = 0; i <= N; i++)
        {
            adj[i] = new List<int>();
            transpose[i] = new List<int>();
        }
        foreach (var edge in edges)
        {
            adj[edge.Item1 - 1].Add(edge.Item2 - 1);
        }
        Array.Fill(vis, 0);
        // Stack to store the components
        Stack<int> st = new Stack<int>();
        for (int i = 0; i < N; i++)
        {
            if (vis[i] == 0)
            {
                DFS(i, adj, st, vis);
            }
        }
        // Transpose the graph and perform the second DFS traversal
        for (int i = 0; i < N; i++)
        {
            foreach (var neighbor in adj[i])
            {
                transpose[neighbor].Add(i);
            }
        }
        Array.Fill(vis, 0);
        Array.Fill(parent, 0);
        Array.Fill(no, 0);
        int par = 0;
        while (st.Count > 0)
        {
            int node = st.Pop();
            if (vis[node] == 0)
            {
                DFS_(node, transpose, vis, par);
                par++;
            }
        }
        // Adjacency matrix to the represent the graph
        // where each node is a strongly connected component
        List<int>[] adjn = new List<int>[100001];
        for (int i = 0; i <= N; i++)
        {
            adjn[i] = new List<int>();
        }
        Array.Fill(vis, 0);
        for (int i = 0; i < N; i++)
        {
            if (vis[i] == 0)
            {
                DFS__(i, vis, adj, adjn, parent);
            }
        }
        // Check nodes with outdegree 0
        int outDegree = 0;
        for (int i = 0; i < par; i++)
        {
            if (adjn[i].Count == 0)
            {
                outDegree++;
            }
        }
        // Decide the count based on the conditions
        if (outDegree > 1 || outDegree == 0)
        {
            return 0;
        }
        else
        {
            for (int i = 0; i < par; i++)
            {
                if (adjn[i].Count == 0)
                {
                    return no[i];
                }
            }
            return 0;
        }
    }
    // Driver code
    static void Main()
    {
        int N = 5;
        int M = 5;
        List<Tuple<int, int>> edges = new List<Tuple<int, int>>
        {
            Tuple.Create(1, 2),
            Tuple.Create(2, 3),
            Tuple.Create(3, 4),
            Tuple.Create(4, 3),
            Tuple.Create(5, 4)
        };
        // Function call
        int ans = CountReachables(N, M, edges);
        Console.WriteLine(ans);
    }
}


Javascript




// This function takes a node and an adjacency list, and performs DFS starting at the node.
// It marks all visited nodes in the vis array and pushes the nodes onto the stack in the order they are visited.
function countReachables(N, M, V) {
    function dfs(node, adj, st, vis) {
        vis[node] = 1;
        for (let it of adj[node]) {
            if (vis[it] === 0) {
                dfs(it, adj, st, vis);
            }
        }
        st.push(node);
    }
 
// This function performs transpose of the graph to determine the strongly connected components (SCCs).
// marks all visited nodes in the vis array and sets the parent and size arrays for each SCC.
 
    function dfs_(node, transpose, vis, par, parent, no) {
        vis[node] = 1;
        parent[node] = par;
        no[par] += 1;
        for (let it of transpose[node]) {
            if (vis[it] === 0) {
                dfs_(it, transpose, vis, par, parent, no);
            }
        }
    }
 
// This function performs build a new graph where each node represents an SCC and there is a directed edge between SCCs if there is a directed edge between any nodes in the SCCs.
    function dfs__(node, vis, adj, adjn, parent) {
        vis[node] = 1;
        for (let it of adj[node]) {
            let par1 = parent[node];
            let par2 = parent[it];
            if (par1 === par2) {
                continue;
            }
            adjn[par1].push(par2);
            if (vis[it] === 0) {
                dfs__(it, vis, adj, adjn, parent);
            }
        }
    }
     
// Creates an adjacency list for the graph and performs the first DFS to fill the stack.
 
    let adj = new Array(N).fill(0).map(() => []);
    for (let i = 0; i < M; i++) {
        adj[V[i][0] - 1].push(V[i][1] - 1);
    }
    let vis = new Array(N).fill(0);
 
    let st = [];
    for (let i = 0; i < N; i++) {
        if (vis[i] === 0) {
            dfs(i, adj, st, vis);
        }
    }
 
// Creates the transpose of the graph and performs the second DFS to determine SCCs and set parent and size arrays.
    let transpose = new Array(N).fill(0).map(() => []);
    for (let i = 0; i < N; i++) {
        transpose[V[i][1] - 1].push(V[i][0] - 1);
    }
    vis = new Array(N).fill(0);
    let parent = new Array(N).fill(0);
    let par = 0;
    let no = new Array(N).fill(0);
    while (st.length > 0) {
        let node = st.pop();
        if (vis[node] === 0) {
            dfs_(node, transpose, vis, par, parent, no);
            par++;
        }
    }
     
// Creates a new adjacency list for the SCC graph and performs the third DFS to build
    let adjn = new Array(N).fill(0).map(() => []);
    vis = new Array(N).fill(0);
    for (let i = 0; i < N; i++) {
        if (vis[i] === 0) {
            dfs__(i, vis, adj, adjn, parent);
        }
    }
 
    let outDegree = 0;
    for(let i = 0; i < par; i++) {
      if(adjn[i].length == 0) {
         outDegree += 1;
     }
   }
   if(outDegree > 1 || outDegree == 0) {
      return 0;
   } else {
    for(let i = 0; i < par; i++) {
        if(adjn[i].length == 0) {
            return no[i];
        }
    }
}
}
 
 
let N = 5;
let M = 5;
let V = [[1, 2], [2, 3], [3, 4], [4, 3], [5, 4]];
 
// Function call
let ans = countReachables(N, M, V);
console.log(ans);


Output

2

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



Similar Reads

Maximize count of nodes disconnected from all other nodes in a Graph
Given two integers N and E which denotes the number of nodes and the number of edges of an undirected graph, the task is to maximize the number of nodes which is not connected to any other node in the graph, without using any self-loops. Examples: Input: N = 5, E = 1 Output: 3 Explanation: Since there is only 1 edge in the graph which can be used t
4 min read
Find a set of at most N/2 nodes from a Graph such that all remaining nodes are directly connected to one of the chosen nodes
Given an integer N, representing the number of nodes present in an undirected graph, with each node valued from 1 to N, and a 2D array Edges[][], representing the pair of vertices connected by an edge, the task is to find a set of at most N/2 nodes such that nodes that are not present in the set, are connected adjacent to any one of the nodes prese
12 min read
Check if every node can me made accessible from a node of a Tree by at most N/2 given operations
Given a Directed Tree consisting of N nodes, the task is to check if there exists a node in the given tree such that all other nodes are reachable by removing any directed edge from the Tree and adding another directed edge between any pair of nodes in the Tree at most floor(N/2) times. If there exists any such node, then print "Yes". Otherwise, pr
6 min read
Number of pair of positions in matrix which are not accessible
Given a positive integer N. Consider a matrix of N X N. No cell can be accessible from any other cell, except the given pair cell in the form of (x1, y1), (x2, y2) i.e there is a path (accessible) between (x2, y2) to (x1, y1). The task is to find the count of pairs (a1, b1), (a2, b2) such that cell (a2, b2) is not accessible from (a1, b1). Examples
8 min read
Check if we can visit all other nodes from any node in given Directed Graph
Given N nodes, where each of them is numbered from 0 to N - 1, and array edges, where there is a directed edge from edges[i][0] to edges[i][1], the task is to find whether we can travel from any node to all other nodes or not. Examples: Input: N = 2, edges[] = {{0, 1}, {1, 0}};Output: TrueExplanation: We can go to node 0 from 1 and node 1 from 0 In
10 min read
Detect cycle in the graph using degrees of nodes of graph
Given a graph, the task is to detect a cycle in the graph using degrees of the nodes in the graph and print all the nodes that are involved in any of the cycles. If there is no cycle in the graph then print -1. Examples: Input: Output: 0 1 2 Approach: Recursively remove all vertices of degree 1. This can be done efficiently by storing a map of vert
11 min read
Minimum cost of path between given nodes containing at most K nodes in a directed and weighted graph
Given a directed weighted graph represented by a 2-D array graph[][] of size n and 3 integers src, dst, and k representing the source point, destination point, and the available number of stops. The task is to minimize the cost of the path between two nodes containing at most K nodes in a directed and weighted graph. If there is no such route, retu
10 min read
Sum of the distances from every node to all other nodes is maximum
Given a tree with N nodes and N-1 edges with root at 1 and given an array of N-1 integers. The task is to assign weights to the edges in the tree such that the sum of the distances from every node to all other nodes is maximum. Examples: Input: Output: 46 Assign the edge 1-2 with weight 5 Assign the edge 2-3 with weight 7 Assign the edge 3-4 with w
14 min read
Sum of length of paths from every node to all other nodes using Tree Rerooting technique
For every node in an undirected tree, find the sum of length of paths from it to all other nodes, using Tree Rerooting technique. Rerooting is a dynamic programming technique in trees. Using this a property dp[i] on tree is calculated, when the tree is rooted at i. Example: Input: Consider the tree shown in the image: [caption width="800"]tree root
23 min read
Minimum of the Maximum distances from any node to all other nodes of given Tree
Given a tree with N vertices and N-1 edges represented by a 2D array edges[], the task is to find the minimum value among the maximum distances from any node to all other nodes of the tree. Examples: Input: N = 4, edges[] = { {1, 2}, {2, 3}, {2, 4} } Output: 1Explanation: The Tree looks like the following. 2 / | \ 1 3 4Maximum distance from house n
8 min read
Article Tags :
Practice Tags :