Given a directed graph, find out if a vertex v is reachable from another vertex u for all vertex pairs (u, v) in the given graph. Here reachable means that there is a path from vertex u to v. The reach-ability matrix is called transitive closure of a graph.
We have discussed an O(V3) solution for this here. The solution was based on Floyd Warshall Algorithm. In this post, DFS solution is discussed. So for dense graph, it would become O(V3) and for sparse graph, it would become O(V2).
Below are the abstract steps of the algorithm.
Create a matrix tc[V][V] that would finally have transitive closure of the given graph. Initialize all entries of tc[][] as 0.
Call DFS for every node of the graph to mark reachable vertices in tc[][]. In recursive calls to DFS, we don't call DFS for an adjacent vertex if it is already marked as reachable in tc[][].
Below is the implementation of the above idea. The code uses adjacency list representation of input graph and builds a matrix tc[V][V] such that tc[u][v] would be true if v is reachable from u.
Implementation:
C++
// C++ program to print transitive closure of a graph#include<bits/stdc++.h>usingnamespacestd;classGraph{intV;// No. of verticesbool**tc;// To store transitive closurelist<int>*adj;// array of adjacency listsvoidDFSUtil(intu,intv);public:Graph(intV);// Constructor// function to add an edge to graphvoidaddEdge(intv,intw){adj[v].push_back(w);}// prints transitive closure matrixvoidtransitiveClosure();};Graph::Graph(intV){this->V=V;adj=newlist<int>[V];tc=newbool*[V];for(inti=0;i<V;i++){tc[i]=newbool[V];memset(tc[i],false,V*sizeof(bool));}}// A recursive DFS traversal function that finds// all reachable vertices for s.voidGraph::DFSUtil(ints,intv){// Mark reachability from s to v as true.tc[s][v]=true;// Explore all vertices adjacent to vfor(intu:adj[v]){// If s is not yet connected to u, explore furtherif(!tc[s][u]){DFSUtil(s,u);}}}// The function to find transitive closure. It uses// recursive DFSUtil()voidGraph::transitiveClosure(){// Call the recursive helper function to print DFS// traversal starting from all vertices one by onefor(inti=0;i<V;i++)DFSUtil(i,i);// Every vertex is reachable from self.for(inti=0;i<V;i++){for(intj=0;j<V;j++)cout<<tc[i][j]<<" ";cout<<endl;}}// Driver codeintmain(){// Create a graph given in the above diagramGraphg(4);g.addEdge(0,1);g.addEdge(0,2);g.addEdge(1,2);g.addEdge(2,0);g.addEdge(2,3);g.addEdge(3,3);cout<<"Transitive closure matrix is \n";g.transitiveClosure();return0;}
Java
// JAVA program to print transitive// closure of a graph.importjava.util.ArrayList;importjava.util.Arrays;// A directed graph using // adjacency list representationpublicclassGraph{// No. of vertices in graphprivateintvertices;// adjacency listprivateArrayList<Integer>[]adjList;// To store transitive closureprivateint[][]tc;// ConstructorpublicGraph(intvertices){// initialise vertex countthis.vertices=vertices;this.tc=newint[this.vertices][this.vertices];// initialise adjacency listinitAdjList();}// utility method to initialise adjacency list@SuppressWarnings("unchecked")privatevoidinitAdjList(){adjList=newArrayList[vertices];for(inti=0;i<vertices;i++){adjList[i]=newArrayList<>();}}// add edge from u to vpublicvoidaddEdge(intu,intv){// Add v to u's list.adjList[u].add(v);}// The function to find transitive// closure. It uses// recursive DFSUtil()publicvoidtransitiveClosure(){// Call the recursive helper// function to print DFS// traversal starting from all// vertices one by onefor(inti=0;i<vertices;i++){dfsUtil(i,i);}for(inti=0;i<vertices;i++){System.out.println(Arrays.toString(tc[i]));}}// A recursive DFS traversal// function that finds// all reachable vertices for sprivatevoiddfsUtil(ints,intv){// Mark reachability from // s to v as true.if(s==v){tc[s][v]=1;}elsetc[s][v]=1;// Find all the vertices reachable// through vfor(intadj:adjList[v]){if(tc[s][adj]==0){dfsUtil(s,adj);}}}// Driver Codepublicstaticvoidmain(String[]args){// Create a graph given// in the above diagramGraphg=newGraph(4);g.addEdge(0,1);g.addEdge(0,2);g.addEdge(1,2);g.addEdge(2,0);g.addEdge(2,3);g.addEdge(3,3);System.out.println("Transitive closure "+"matrix is");g.transitiveClosure();}}// This code is contributed// by Himanshu Shekhar
C#
// C# program to print transitive// closure of a graph.usingSystem;usingSystem.Collections.Generic;// A directed graph using// adjacency list representationpublicclassGraph{// No. of vertices in graphprivateintvertices;// adjacency listprivateList<int>[]adjList;// To store transitive closureprivateint[,]tc;// ConstructorpublicGraph(intvertices){// initialise vertex countthis.vertices=vertices;this.tc=newint[this.vertices,this.vertices];// initialise adjacency listinitAdjList();}// utility method to initialise adjacency listprivatevoidinitAdjList(){adjList=newList<int>[vertices];for(inti=0;i<vertices;i++){adjList[i]=newList<int>();}}// add edge from u to vpublicvoidaddEdge(intu,intv){// Add v to u's list.adjList[u].Add(v);}// The function to find transitive// closure. It uses// recursive DFSUtil()publicvoidtransitiveClosure(){// Call the recursive helper// function to print DFS// traversal starting from all// vertices one by onefor(inti=0;i<vertices;i++){dfsUtil(i,i);}for(inti=0;i<vertices;i++){for(intj=0;j<vertices;j++)Console.Write(tc[i,j]+" ");Console.WriteLine();}}// A recursive DFS traversal// function that finds// all reachable vertices for sprivatevoiddfsUtil(ints,intv){// Mark reachability from// s to v as true.tc[s,v]=1;// Find all the vertices reachable// through vforeach(intadjinadjList[v]){if(tc[s,adj]==0){dfsUtil(s,adj);}}}// Driver CodepublicstaticvoidMain(String[]args){// Create a graph given// in the above diagramGraphg=newGraph(4);g.addEdge(0,1);g.addEdge(0,2);g.addEdge(1,2);g.addEdge(2,0);g.addEdge(2,3);g.addEdge(3,3);Console.WriteLine("Transitive closure "+"matrix is");g.transitiveClosure();}}// This code is contributed by Rajput-Ji
JavaScript
<script>/* Javascript program to print transitive closure of a graph*/classGraph{// Constructorconstructor(v){this.V=v;this.adj=newArray(v);this.tc=Array.from(Array(v),()=>newArray(v).fill(0));for(leti=0;i<v;i++)this.adj[i]=[];}// function to add an edge to graphaddEdge(v,w){this.adj[v].push(w);}// A recursive DFS traversal function that finds// all reachable vertices for s.DFSUtil(s,v){// Mark reachability from s to v as true.this.tc[s][v]=1;// Find all the vertices reachable through vfor(letiofthis.adj[v].values()){if(this.tc[s][i]==0)this.DFSUtil(s,i);}}// The function to find transitive closure. It uses// recursive DFSUtil()transitiveClosure(){// Call the recursive helper function to print DFS// traversal starting from all vertices one by onefor(leti=0;i<this.V;i++)this.DFSUtil(i,i);// Every vertex is reachable from selfdocument.write("Transitive closure matrix is<br />")for(leti=0;i<this.V;i++){for(letj=0;j<this.V;j++)document.write(this.tc[i][j]+" ");document.write("<br />")}}};// driver codeg=newGraph(4);g.addEdge(0,1);g.addEdge(0,2);g.addEdge(1,2);g.addEdge(2,0);g.addEdge(2,3);g.addEdge(3,3);g.transitiveClosure();// This code is contributed by cavi4762.</script>
Python3
# Python program to print transitive# closure of a graph.fromcollectionsimportdefaultdictclassGraph:def__init__(self,vertices):# No. of verticesself.V=vertices# default dictionary to store graphself.graph=defaultdict(list)# To store transitive closureself.tc=[[0forjinrange(self.V)]foriinrange(self.V)]# function to add an edge to graphdefaddEdge(self,u,v):self.graph[u].append(v)# A recursive DFS traversal function that finds# all reachable vertices for sdefDFSUtil(self,s,v):# Mark reachability from s to v as true.if(s==v):if(vinself.graph[s]):self.tc[s][v]=1else:self.tc[s][v]=1# Find all the vertices reachable through vforiinself.graph[v]:ifself.tc[s][i]==0:ifs==i:self.tc[s][i]=1else:self.DFSUtil(s,i)# The function to find transitive closure. It uses# recursive DFSUtil()deftransitiveClosure(self):# Call the recursive helper function to print DFS# traversal starting from all vertices one by oneforiinrange(self.V):self.DFSUtil(i,i)print(self.tc)# Create a graph given in the above diagramg=Graph(4)g.addEdge(0,1)g.addEdge(0,2)g.addEdge(1,2)g.addEdge(2,0)g.addEdge(2,3)g.addEdge(3,3)g.transitiveClosure()
Time Complexity : O(V^3) where V is the number of vertexes . For dense graph, it would become O(V3) and for sparse graph, it would become O(V2). Auxiliary Space: O(V^2) where V is number of vertices.
We use cookies to ensure you have the best browsing experience on our website. By using our site, you
acknowledge that you have read and understood our
Cookie Policy &
Privacy Policy
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.