Open In App

Inverse Graph

Last Updated : 02 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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()

Output
Original 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();

Output
Original 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:

Problem

Problem Link

Strongly Connected Components (Kosaraju’s Algo)

Practice Now

Number of Good Components

Practice Now

Mother Vertex

Practice Now



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads