Inverse Graph
Last Updated :
02 Apr, 2024
What is Inverse Graph?
Inverse of a directed graph G is another directed graph on the same set of vertices with all the edges reversed as present in G. For every directed edge (u, v) present in G, the inverse of the graph has the directed edge (v, u).
Why to use Inverse Graph?
The idea behind using Inverse Graph is to analyze paths and connectivity of a Directed Graph. Several graph algorithms become more straightforward when applied to transpose graphs. For instance, algorithms like depth-first search (DFS) and strongly connected components (SCC) algorithms can be efficiently implemented on transpose graphs. Inverse Graph is also quite useful for topological sort on Directed Acyclic Graphs.
Implementation:
Inverse graph can be implemented by simply reversing the direction of all the directed edges.
Implementation of Inverse Graph (Adjacency List):
C++
#include <bits/stdc++.h>
using namespace std;
void printGraph(vector<vector<int>> &graph, int V) {
for(int node= 0; node < V; node++) {
cout << node << " -> ";
for(int child: graph[node]) {
cout << child << " ";
}
cout << endl;
}
}
int main() {
int V = 5, E = 6;
vector<vector<int>> edges = {{0, 1}, {0, 2}, {2, 3}, {2, 0}, {1, 3}, {3, 4}, {4, 2}};
vector<vector<int>> graph(V);
for(auto edge: edges) {
graph[edge[0]].push_back(edge[1]);
}
cout << "Original Graph: " << endl;
printGraph(graph, V);
vector<vector<int>> inverseGraph(V);
for(auto edge: edges) {
inverseGraph[edge[1]].push_back(edge[0]);
}
cout << "Inverse Graph: " << endl;
printGraph(inverseGraph, V);
}
Java
import java.util.ArrayList;
public class GraphOperations {
// Function to print the graph
static void
printGraph(ArrayList<ArrayList<Integer> > graph, int V)
{
for (int node = 0; node < V; node++) {
System.out.print(node + " -> ");
for (int child : graph.get(node)) {
System.out.print(child + " ");
}
System.out.println();
}
}
public static void main(String[] args)
{
int V = 5, E = 6;
// Edges representing the connections between nodes
int[][] edges
= { { 0, 1 }, { 0, 2 }, { 2, 3 }, { 2, 0 },
{ 1, 3 }, { 3, 4 }, { 4, 2 } };
// Creating the original graph as an adjacency list
ArrayList<ArrayList<Integer> > graph
= new ArrayList<>();
for (int i = 0; i < V; i++) {
graph.add(new ArrayList<>());
}
// Building the original graph using the edges
for (int[] edge : edges) {
graph.get(edge[0]).add(edge[1]);
}
// Printing the original graph
System.out.println("Original Graph: ");
printGraph(graph, V);
// Creating the inverse graph as an adjacency list
ArrayList<ArrayList<Integer> > inverseGraph
= new ArrayList<>();
for (int i = 0; i < V; i++) {
inverseGraph.add(new ArrayList<>());
}
// Building the inverse graph using the edges
for (int[] edge : edges) {
inverseGraph.get(edge[1]).add(edge[0]);
}
// Printing the inverse graph
System.out.println("Inverse Graph: ");
printGraph(inverseGraph, V);
}
}
// This code is contributed by rambabuguphka
C#
using System;
using System.Collections.Generic;
public class MainClass {
// Function to print the graph
static void PrintGraph(List<List<int>> graph, int V) {
// Loop through each node in the graph
for (int node = 0; node < V; node++) {
// Print the current node
Console.Write(node + " -> ");
// Print all adjacent nodes of the current node
foreach (int child in graph[node]) {
Console.Write(child + " ");
}
// Move to the next line for the next node
Console.WriteLine();
}
}
public static void Main (string[] args) {
// Define the number of vertices (nodes) in the graph
int V = 5;
// Define the edges of the graph as pairs of vertices
List<List<int>> edges = new List<List<int>> {
new List<int> {0, 1}, new List<int> {0, 2}, new List<int> {2, 3},
new List<int> {2, 0}, new List<int> {1, 3}, new List<int> {3, 4}, new List<int> {4, 2}
};
// Create the adjacency list representation of the graph
List<List<int>> graph = new List<List<int>>(V);
for (int i = 0; i < V; i++) {
graph.Add(new List<int>());
}
// Populate the adjacency list with edges
foreach (var edge in edges) {
graph[edge[0]].Add(edge[1]);
}
// Print the original graph
Console.WriteLine("Original Graph:");
PrintGraph(graph, V);
// Create the inverse graph by reversing the edges
List<List<int>> inverseGraph = new List<List<int>>(V);
for (int i = 0; i < V; i++) {
inverseGraph.Add(new List<int>());
}
// Populate the inverse graph with reversed edges
foreach (var edge in edges) {
inverseGraph[edge[1]].Add(edge[0]);
}
// Print the inverse graph
Console.WriteLine("Inverse Graph:");
PrintGraph(inverseGraph, V);
}
}
Javascript
function GFG(graph) {
// Iterate over each node in tgraph
for (let node = 0; node < graph.length; node++) {
// Print the node and its adjacent nodes
process.stdout.write(node + " -> ");
console.log(graph[node].join(" "));
}
}
// Main function
function main() {
const V = 5;
const edges = [[0, 1], [0, 2], [2, 3], [2, 0], [1, 3], [3, 4], [4, 2]];
// The Original graph
const graph = Array.from({ length: V }, () => []);
// Build the original graph
for (const [u, v] of edges) {
graph[u].push(v);
}
// Print the original graph
console.log("Original Graph:");
GFG(graph);
const inverseGraph = Array.from({ length: V }, () => []);
// Build the inverse graph
for (const [u, v] of edges) {
inverseGraph[v].push(u);
}
// Print the inverse graph
console.log("Inverse Graph:");
GFG(inverseGraph);
}
main();
Python3
class GraphOperations:
# Function to print the graph
@staticmethod
def print_graph(graph, V):
for node in range(V):
print(node, "->", " ".join(map(str, graph[node])))
@staticmethod
def main():
V = 5
E = 6
# Edges representing the connections between nodes
edges = [[0, 1], [0, 2], [2, 3], [2, 0], [1, 3], [3, 4], [4, 2]]
# Creating the original graph as an adjacency list
graph = [[] for _ in range(V)]
# Building the original graph using the edges
for edge in edges:
graph[edge[0]].append(edge[1])
# Printing the original graph
print("Original Graph:")
GraphOperations.print_graph(graph, V)
# Creating the inverse graph as an adjacency list
inverse_graph = [[] for _ in range(V)]
# Building the inverse graph using the edges
for edge in edges:
inverse_graph[edge[1]].append(edge[0])
# Printing the inverse graph
print("Inverse Graph:")
GraphOperations.print_graph(inverse_graph, V)
# Call the main method
GraphOperations.main()
OutputOriginal Graph:
0 -> 1 2
1 -> 3
2 -> 3 0
3 -> 4
4 -> 2
Inverse Graph:
0 -> 2
1 -> 0
2 -> 0 4
3 -> 2 1
4 -> 3
Implementation of Inverse Graph (Adjacency Matrix):
C++
#include <iostream>
#include <vector>
using namespace std;
void printGraph(vector<vector<int>> & graph, int V)
{
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
cout << graph[i][j] << " ";
}
cout << "\n";
}
}
int main()
{
int V = 5, E = 6;
vector<vector<int>> edges
= { { 0, 1 }, { 0, 2 }, { 2, 3 }, { 2, 0 },
{ 1, 3 }, { 3, 4 }, { 4, 2 } };
vector<vector<int>> graph = { { 0, 1, 1, 0, 0 },
{ 0, 0, 1, 0, 0 },
{ 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1 },
{ 0, 0, 1, 0, 0 } };
cout << "Original Graph: " << endl;
printGraph(graph, V);
vector<vector<int>> inverseGraph(V, vector<int>(V, 0));
for(int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
if (graph[i][j] == 1) {
inverseGraph[j][i] = 1;
}
}
}
cout << "Inverse Graph: " << endl;
printGraph(inverseGraph, V);
}
Java
import java.util.*;
public class Main {
// Function to print a graph represented by a 2D array
static void printGraph(int[][] graph, int V) {
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
System.out.print(graph[i][j] + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
int V = 5, E = 6;
int[][] graph = { { 0, 1, 1, 0, 0 },
{ 0, 0, 1, 0, 0 },
{ 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1 },
{ 0, 0, 1, 0, 0 } };
// Print the original graph
System.out.println("Original Graph:");
printGraph(graph, V);
// Create an inverse graph based on the original graph
int[][] inverseGraph = new int[V][V];
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
if (graph[i][j] == 1) {
inverseGraph[j][i] = 1;
}
}
}
// Print the inverse graph
System.out.println("Inverse Graph:");
printGraph(inverseGraph, V);
}
}
Python
# Function to print a graph represented by a 2D array
def print_graph(graph, V):
for i in range(V):
print(" ".join(map(str, graph[i])))
def main():
V, E = 5, 6
graph = [
[0, 1, 1, 0, 0],
[0, 0, 1, 0, 0],
[1, 0, 0, 0, 0],
[0, 0, 0, 0, 1],
[0, 0, 1, 0, 0]
]
# Print the original graph
print("Original Graph:")
print_graph(graph, V)
# Create an inverse graph based on the original graph
inverse_graph = [[0] * V for _ in range(V)]
for i in range(V):
for j in range(V):
if graph[i][j] == 1:
inverse_graph[j][i] = 1
# Print the inverse graph
print("Inverse Graph:")
print_graph(inverse_graph, V)
main()
JavaScript
// Function to print a graph represented by a 2D array
function printGraph(graph, V) {
for (let i = 0; i < V; i++) {
console.log(graph[i].join(" "));
}
}
function main() {
const V = 5, E = 6;
const graph = [
[0, 1, 1, 0, 0],
[0, 0, 1, 0, 0],
[1, 0, 0, 0, 0],
[0, 0, 0, 0, 1],
[0, 0, 1, 0, 0]
];
// Print the original graph
console.log("Original Graph:");
printGraph(graph, V);
// Create an inverse graph based on the original graph
const inverseGraph = new Array(V).fill(null).map(() => new Array(V).fill(0));
for (let i = 0; i < V; i++) {
for (let j = 0; j < V; j++) {
if (graph[i][j] === 1) {
inverseGraph[j][i] = 1;
}
}
}
// Print the inverse graph
console.log("Inverse Graph:");
printGraph(inverseGraph, V);
}
main();
OutputOriginal Graph:
0 1 1 0 0
0 0 1 0 0
1 0 0 0 0
0 0 0 0 1
0 0 1 0 0
Inverse Graph:
0 0 1 0 0
1 0 0 0 0
1 1 0 0 1
0 0 0 0 0
0 0 0 1 0
Use cases of Inverse Graph:
To find the strongly connected components in a directed graph (Kosaraju’s algorithm):
In Kosaraju’s Algorithm, we run a DFS on the inverse of the original graph and store the nodes in order of their finishing times, that is a node is stored when all of its children have already been stored in previous DFS calls. The reason is that the finishing times obtained from the DFS traversal of the Inverse Graph are in topological order. When we perform DFS on G starting from the vertex with the highest finishing time, we are effectively exploring one strongly connected component at a time.
Practice Problems:
Share your thoughts in the comments
Please Login to comment...