Program to reverse the directed graph in Python

A directed graph reversal means changing the direction of all edges − if an edge goes from node u to v, it becomes an edge from v to u. Given an adjacency list representation, we need to create the reverse graph where all edge directions are flipped.

Problem Understanding

Consider a directed graph with nodes numbered from 0 to n-1. If the original graph has an edge from node i to node j, the reversed graph will have an edge from node j to node i.

Original Graph 0 1 2 ? Reversed Graph 0 1 2

Algorithm

The algorithm iterates through each node and its adjacent nodes, then adds reverse edges to the result ?

  1. Create an empty adjacency list for the reversed graph
  2. For each node i and its adjacency list, add i to the adjacency list of each neighbor
  3. Return the reversed adjacency list

Implementation

def reverse_graph(graph):
    """
    Reverse a directed graph represented as adjacency list
    Args: graph - list of lists representing adjacency list
    Returns: reversed graph as adjacency list
    """
    n = len(graph)
    reversed_graph = [[] for _ in range(n)]
    
    # For each node and its neighbors
    for node in range(n):
        for neighbor in graph[node]:
            # Add reverse edge: neighbor -> node
            reversed_graph[neighbor].append(node)
    
    return reversed_graph

# Example usage
original_graph = [[1, 2], [4], [4], [1, 2], [3]]
result = reverse_graph(original_graph)
print("Original graph:", original_graph)
print("Reversed graph:", result)
Original graph: [[1, 2], [4], [4], [1, 2], [3]]
Reversed graph: [[], [0, 3], [0, 3], [4], [1, 2]]

Step-by-Step Trace

Let's trace through the algorithm with the example graph ?

def reverse_graph_with_trace(graph):
    n = len(graph)
    reversed_graph = [[] for _ in range(n)]
    
    print(f"Initial reversed graph: {reversed_graph}")
    
    for node in range(n):
        print(f"\nProcessing node {node} with neighbors {graph[node]}:")
        for neighbor in graph[node]:
            reversed_graph[neighbor].append(node)
            print(f"  Added edge {neighbor} -> {node}")
            print(f"  Current state: {reversed_graph}")
    
    return reversed_graph

# Trace the example
graph = [[1, 2], [4], [4], [1, 2], [3]]
result = reverse_graph_with_trace(graph)
Initial reversed graph: [[], [], [], [], []]

Processing node 0 with neighbors [1, 2]:
  Added edge 1 -> 0
  Current state: [[], [0], [], [], []]
  Added edge 2 -> 0
  Current state: [[], [0], [0], [], []]

Processing node 1 with neighbors [4]:
  Added edge 4 -> 1
  Current state: [[], [0], [0], [], [1]]

Processing node 2 with neighbors [4]:
  Added edge 4 -> 2
  Current state: [[], [0], [0], [], [1, 2]]

Processing node 3 with neighbors [1, 2]:
  Added edge 1 -> 3
  Current state: [[], [0, 3], [0], [], [1, 2]]
  Added edge 2 -> 3
  Current state: [[], [0, 3], [0, 3], [], [1, 2]]

Processing node 4 with neighbors [3]:
  Added edge 3 -> 4
  Current state: [[], [0, 3], [0, 3], [4], [1, 2]]

Time and Space Complexity

Aspect Complexity Explanation
Time Complexity O(V + E) Visit each vertex and edge once
Space Complexity O(V + E) Store reversed adjacency list

Where V is the number of vertices and E is the number of edges in the graph.

Conclusion

Reversing a directed graph involves creating a new adjacency list where each edge direction is flipped. The algorithm efficiently processes each edge once, making it optimal for this operation with O(V + E) time complexity.

Updated on: 2026-03-25T11:34:37+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements