Given a directed Eulerian graph, the task is to print an Euler circuit. An Euler circuit is a path that traverses every edge of a graph exactly once, and the path ends on the starting vertex.
Conditions for Eulerian circuit in a Directed Grpag : (1) All vertices belong to a single strongly connected component. (2) All vertices have same in-degree and out-degree. Note that for an undirected graph, the condition is different (all vertices have even degree)
Approach:
Choose any starting vertex v, and follow a trail of edges from that vertex until returning to v. It is not possible to get stuck at any vertex other than v, because indegree and outdegree of every vertex must be same, when the trail enters another vertex w there must be an unused edge leaving w. The tour formed in this way is a closed tour, but may not cover all the vertices and edges of the initial graph.
As long as there exists a vertex u that belongs to the current tour, but that has adjacent edges not part of the tour, start another trail from u, following unused edges until returning to u, and join the tour formed in this way to the previous tour.
Illustration:
Taking example of the above graph with 5 nodes : adj = {{2, 3}, {0}, {1}, {4}, {0}}.
Start at vertex 0:
Current Path: [0]
Circuit: []
Vertex 0 → 3:
Current Path: [0, 3]
Circuit: []
Vertex 3 → 4:
Current Path: [0, 3, 4]
Circuit: []
Vertex 4 → 0:
Current Path: [0, 3, 4, 0]
Circuit: []
Vertex 0 → 2:
Current Path: [0, 3, 4, 0, 2]
Circuit: []
Vertex 2 → 1:
Current Path: [0, 3, 4, 0, 2, 1]
Circuit: []
Vertex 1 → 0:
Current Path: [0, 3, 4, 0, 2, 1, 0]
Circuit: []
Backtrack to vertex 0: Add 0 to circuit.
Current Path: [0, 3, 4, 0, 2, 1]
Circuit: [0]
Backtrack to vertex 1: Add 1 to circuit.
Current Path: [0, 3, 4, 0, 2]
Circuit: [0, 1]
Backtrack to vertex 2: Add 2 to circuit.
Current Path: [0, 3, 4, 0]
Circuit: [0, 1, 2]
Backtrack to vertex 0: Add 0 to circuit.
Current Path: [0, 3, 4]
Circuit: [0, 1, 2, 0]
Backtrack to vertex 4: Add 4 to circuit.
Current Path: [0, 3]
Circuit: [0, 1, 2, 0, 4]
Backtrack to vertex 3: Add 3 to circuit.
Current Path: [0]
Circuit: [0, 1, 2, 0, 4, 3]
Backtrack to vertex 0: Add 0 to circuit.
Current Path: []
Circuit: [0, 1, 2, 0, 4, 3, 0]
Below is the implementation for the above approach:
C++
// C++ program to print Eulerian circuit in given// directed graph using Hierholzer algorithm#include<bits/stdc++.h>usingnamespacestd;// Function to print Eulerian circuitvector<int>printCircuit(vector<vector<int>>&adj){intn=adj.size();if(n==0)return{};// Maintain a stack to keep vertices// We can start from any vertex, here we start with 0vector<int>currPath;currPath.push_back(0);// list to store final circuitvector<int>circuit;while(currPath.size()>0){intcurrNode=currPath[currPath.size()-1];// If there's remaining edge in adjacency list// of the current vertexif(adj[currNode].size()>0){// Find and remove the next vertex that is// adjacent to the current vertexintnextNode=adj[currNode].back();adj[currNode].pop_back();// Push the new vertex to the stackcurrPath.push_back(nextNode);}// back-track to find remaining circuitelse{// Remove the current vertex and// put it in the circuitcircuit.push_back(currPath.back());currPath.pop_back();}}// reverse the result vector reverse(circuit.begin(),circuit.end());returncircuit;}intmain(){vector<vector<int>>adj={{2,3},{0},{1},{4},{0}};vector<int>ans=printCircuit(adj);for(autov:ans)cout<<v<<" ";cout<<endl;return0;}
Java
// Java program to print Eulerian circuit in given// directed graph using Hierholzer algorithmimportjava.util.*;classGfG{// Function to print Eulerian circuitstaticList<Integer>printCircuit(List<List<Integer>>adj){intn=adj.size();if(n==0)returnnewArrayList<>();// Maintain a stack to keep vertices// We can start from any vertex, here we start with 0List<Integer>currPath=newArrayList<>();currPath.add(0);// list to store final circuitList<Integer>circuit=newArrayList<>();while(currPath.size()>0){intcurrNode=currPath.get(currPath.size()-1);// If there's remaining edge in adjacency list// of the current vertexif(adj.get(currNode).size()>0){// Find and remove the next vertex that is// adjacent to the current vertexintnextNode=adj.get(currNode).get(adj.get(currNode).size()-1);adj.get(currNode).remove(adj.get(currNode).size()-1);// Push the new vertex to the stackcurrPath.add(nextNode);}// back-track to find remaining circuitelse{// Remove the current vertex and// put it in the circuitcircuit.add(currPath.get(currPath.size()-1));currPath.remove(currPath.size()-1);}}// reverse the result vectorCollections.reverse(circuit);returncircuit;}publicstaticvoidmain(String[]args){List<List<Integer>>adj=newArrayList<>();adj.add(newArrayList<>(Arrays.asList(2,3)));adj.add(newArrayList<>(Arrays.asList(0)));adj.add(newArrayList<>(Arrays.asList(1)));adj.add(newArrayList<>(Arrays.asList(4)));adj.add(newArrayList<>(Arrays.asList(0)));List<Integer>ans=printCircuit(adj);for(intv:ans)System.out.print(v+" ");System.out.println();}}
Python
# Python program to print Eulerian circuit in given# directed graph using Hierholzer algorithm# Function to print Eulerian circuitdefprintCircuit(adj):n=len(adj)ifn==0:return[]# Maintain a stack to keep vertices# We can start from any vertex, here we start with 0currPath=[0]# list to store final circuitcircuit=[]whilelen(currPath)>0:currNode=currPath[-1]# If there's remaining edge in adjacency list# of the current vertexiflen(adj[currNode])>0:# Find and remove the next vertex that is# adjacent to the current vertexnextNode=adj[currNode].pop()# Push the new vertex to the stackcurrPath.append(nextNode)# back-track to find remaining circuitelse:# Remove the current vertex and# put it in the circuitcircuit.append(currPath.pop())# reverse the result vectorcircuit.reverse()returncircuitif__name__=="__main__":adj=[[2,3],[0],[1],[4],[0]]ans=printCircuit(adj)forvinans:print(v,end=" ")print()
C#
// C# program to print Eulerian circuit in given// directed graph using Hierholzer algorithmusingSystem;usingSystem.Collections.Generic;classGfG{// Function to print Eulerian circuitstaticList<int>printCircuit(List<List<int>>adj){intn=adj.Count;if(n==0)returnnewList<int>();// Maintain a stack to keep vertices// We can start from any vertex, here we start with 0List<int>currPath=newList<int>{0};// list to store final circuitList<int>circuit=newList<int>();while(currPath.Count>0){intcurrNode=currPath[currPath.Count-1];// If there's remaining edge in adjacency list// of the current vertexif(adj[currNode].Count>0){// Find and remove the next vertex that is// adjacent to the current vertexintnextNode=adj[currNode][adj[currNode].Count-1];adj[currNode].RemoveAt(adj[currNode].Count-1);// Push the new vertex to the stackcurrPath.Add(nextNode);}// back-track to find remaining circuitelse{// Remove the current vertex and// put it in the circuitcircuit.Add(currPath[currPath.Count-1]);currPath.RemoveAt(currPath.Count-1);}}// reverse the result vectorcircuit.Reverse();returncircuit;}staticvoidMain(string[]args){List<List<int>>adj=newList<List<int>>{newList<int>{2,3},newList<int>{0},newList<int>{1},newList<int>{4},newList<int>{0}};List<int>ans=printCircuit(adj);foreach(intvinans){Console.Write(v+" ");}Console.WriteLine();}}
JavaScript
// JavaScript program to print Eulerian circuit in given// directed graph using Hierholzer algorithm// Function to print Eulerian circuitfunctionprintCircuit(adj){letn=adj.length;if(n===0)return[];// Maintain a stack to keep vertices// We can start from any vertex, here we start with 0letcurrPath=[0];// list to store final circuitletcircuit=[];while(currPath.length>0){letcurrNode=currPath[currPath.length-1];// If there's remaining edge in adjacency list// of the current vertexif(adj[currNode].length>0){// Find and remove the next vertex that is// adjacent to the current vertexletnextNode=adj[currNode].pop();// Push the new vertex to the stackcurrPath.push(nextNode);}// back-track to find remaining circuitelse{// Remove the current vertex and// put it in the circuitcircuit.push(currPath.pop());}}// reverse the result vectorcircuit.reverse();returncircuit;}letadj=[[2,3],[0],[1],[4],[0]];letans=printCircuit(adj);for(letvofans){console.log(v," ");}
Output
0 3 4 0 2 1 0
Time Complexity : O(V + E), where V is the number of vertices and E is the number of edges in the graph. The reason for this is because the algorithm performs a depth-first search (DFS) and visits each vertex and each edge exactly once. So, for each vertex, it takes O(1) time to visit it and for each edge, it takes O(1) time to traverse it.
Space complexity : O(V + E), as the algorithm uses a stack to store the current path and a list to store the final circuit. The maximum size of the stack can be V + E at worst, so the space complexity is O(V + E).