Eulerian path and circuit for undirected graph

Last Updated : 4 Oct, 2026

Given an undirected graph represented using an adjacency list adj , where adj[i] stores all the nodes that have an edge with i,

  • Return 2 if the graph contains an Eulerian circuit. An Eulerian Cycle visits every edge exactly once and starts and ends at the same vertex. A graph with Eulerian Cycle is called Eulerian.
  • Else If the graph contains an eulerian path, return 1. An Eulerian Path is a path that visits every edge exactly once but starts and ends at different vertices, it is called Semi-Eulerian.
  • Otherwise, return 0.

Examples:

Input:

blobid0_1745469108

Output: 2
Explanation:
Following is an eulerian circuit in the mentioned graph: 1 -> 2 -> 0 -> 1

Input:

blobid4_1745469310

Output: 1
Explanation:
Following is an eulerian path in the mentioned graph: 1 -> 0 -> 2

Try It Yourself
redirect icon

[Naive Approach] Backtracking to Traverse Every Edge - O(V × E!) Time and O(V + E) Space

The idea is to try every possible traversal using DFS and backtracking.

  • Starting from each vertex, recursively traverse every unvisited edge exactly once. If all edges are visited in a traversal, an Euler Path exists.
  • If the traversal also ends at the starting vertex, it is an Euler Circuit.
  • If no such traversal is found after trying all starting vertices, the graph is not Eulerian.

Working of the Approach:

  • Build the graph and assign a unique ID to every edge.
  • Start a DFS with backtracking from each vertex, trying to traverse every edge exactly once.
  • During DFS, mark an edge as visited before traversing it and unmark it while backtracking.
  • If all edges are visited exactly once, check whether the traversal ends at the starting vertex to determine whether it is an Euler Circuit or an Euler Path.
  • If no traversal visits all edges exactly once, return 0.
C++
#include <bits/stdc++.h>
using namespace std;

// Tries to traverse all edges exactly once.
bool dfs(int u, int start, int usedEdges, int totalEdges, vector<vector<pair<int, int>>> &adj,
         vector<bool> &used, bool &isCircuit)
{
    if (usedEdges == totalEdges)
    {
        if (u == start)
            isCircuit = true;
        return true;
    }

    for (auto [v, id] : adj[u])
    {
        if (!used[id])
        {
            used[id] = true;

            if (dfs(v, start, usedEdges + 1, totalEdges, adj, used, isCircuit))
                return true;

            used[id] = false;
        }
    }

    return false;
}

int isEulerCircuit(int V, vector<vector<int>> &graph)
{
    vector<vector<pair<int, int>>> adj(V);

    int id = 0;

    // Assign a unique id to every undirected edge.
    for (int u = 0; u < V; u++)
    {
        for (int v : graph[u])
        {
            if (u < v)
            {
                adj[u].push_back({v, id});
                adj[v].push_back({u, id});
                id++;
            }
        }
    }

    int E = id;

    bool foundPath = false;
    bool foundCircuit = false;

    // Try every starting vertex.
    for (int start = 0; start < V; start++)
    {
        vector<bool> used(E, false);
        bool isCircuit = false;

        if (dfs(start, start, 0, E, adj, used, isCircuit))
        {
            foundPath = true;

            if (isCircuit)
                foundCircuit = true;
        }
    }

    if (foundCircuit)
        return 2;
    if (foundPath)
        return 1;
    return 0;
}

int main()
{
    int V = 3;
    vector<vector<int>> adj(V);

    // Add undirected edges:
    // 0 - 1
    // |  /
    // 2
    adj[0] = {1, 2};
    adj[1] = {0, 2};
    adj[2] = {0, 1};

    cout << isEulerCircuit(V, adj);

    return 0;
}
Java
import java.util.*;

class Pair {
    int v, id;

    Pair(int v, int id)
    {
        this.v = v;
        this.id = id;
    }
}

public class GFG {

    // Tries to traverse all edges exactly once.
    static boolean dfs(int u, int start, int usedEdges,
                       int totalEdges,
                       ArrayList<ArrayList<Pair> > adj,
                       boolean[] used, boolean[] isCircuit)
    {

        if (usedEdges == totalEdges) {
            if (u == start)
                isCircuit[0] = true;
            return true;
        }

        for (Pair p : adj.get(u)) {
            if (!used[p.id]) {
                used[p.id] = true;

                if (dfs(p.v, start, usedEdges + 1,
                        totalEdges, adj, used, isCircuit))
                    return true;

                used[p.id] = false;
            }
        }

        return false;
    }

    static int isEulerCircuit(int V, int[][] graph)
    {

        ArrayList<ArrayList<Pair> > adj = new ArrayList<>();

        for (int i = 0; i < V; i++)
            adj.add(new ArrayList<>());

        int id = 0;

        // Assign a unique id to every undirected edge.
        for (int u = 0; u < V; u++) {
            for (int v : graph[u]) {
                if (u < v) {
                    adj.get(u).add(new Pair(v, id));
                    adj.get(v).add(new Pair(u, id));
                    id++;
                }
            }
        }

        int E = id;

        boolean foundPath = false;
        boolean foundCircuit = false;

        // Try every starting vertex.
        for (int start = 0; start < V; start++) {

            boolean[] used = new boolean[E];
            boolean[] isCircuit = new boolean[1];

            if (dfs(start, start, 0, E, adj, used,
                    isCircuit)) {

                foundPath = true;

                if (isCircuit[0])
                    foundCircuit = true;
            }
        }

        if (foundCircuit)
            return 2;
        if (foundPath)
            return 1;
        return 0;
    }

    public static void main(String[] args)
    {

        int V = 3;

        int[][] adj = { { 1, 2 }, { 0, 2 }, { 0, 1 } };

        System.out.println(isEulerCircuit(V, adj));
    }
}
Python
# Tries to traverse all edges exactly once.
def dfs(u, start, usedEdges, totalEdges, adj, used, isCircuit):
    if usedEdges == totalEdges:
        if u == start:
            isCircuit[0] = True
        return True

    for v, edgeId in adj[u]:
        if not used[edgeId]:
            used[edgeId] = True

            if dfs(v, start, usedEdges + 1, totalEdges,
                   adj, used, isCircuit):
                return True

            used[edgeId] = False

    return False


def isEulerCircuit(V, graph):
    adj = [[] for _ in range(V)]

    edgeId = 0

    # Assign a unique id to every undirected edge.
    for u in range(V):
        for v in graph[u]:
            if u < v:
                adj[u].append((v, edgeId))
                adj[v].append((u, edgeId))
                edgeId += 1

    E = edgeId

    foundPath = False
    foundCircuit = False

    # Try every starting vertex.
    for start in range(V):
        used = [False] * E
        isCircuit = [False]

        if dfs(start, start, 0, E, adj, used, isCircuit):
            foundPath = True

            if isCircuit[0]:
                foundCircuit = True

    if foundCircuit:
        return 2
    if foundPath:
        return 1
    return 0


if __name__ == "__main__":
    V = 3

    # Add undirected edges:
    # 0 - 1
    # |  /
    # 2
    adj = [
        [1, 2],
        [0, 2],
        [0, 1]
    ]

    print(isEulerCircuit(V, adj))
C#
using System;
using System.Collections.Generic;

class Pair {
    public int v, id;

    public Pair(int v, int id)
    {
        this.v = v;
        this.id = id;
    }
}

class GFG {
    // Tries to traverse all edges exactly once.
    static bool dfs(int u, int start, int usedEdges,
                    int totalEdges, List<List<Pair> > adj,
                    bool[] used, ref bool isCircuit)
    {
        if (usedEdges == totalEdges) {
            if (u == start)
                isCircuit = true;

            return true;
        }

        foreach(Pair p in adj[u])
        {
            if (!used[p.id]) {
                used[p.id] = true;

                if (dfs(p.v, start, usedEdges + 1,
                        totalEdges, adj, used,
                        ref isCircuit))
                    return true;

                used[p.id] = false;
            }
        }

        return false;
    }

    static int isEulerCircuit(int V, int[][] graph)
    {
        List<List<Pair> > adj = new List<List<Pair> >();

        for (int i = 0; i < V; i++)
            adj.Add(new List<Pair>());

        int id = 0;

        // Assign a unique id to every undirected edge.
        for (int u = 0; u < V; u++) {
            foreach(int v in graph[u])
            {
                if (u < v) {
                    adj[u].Add(new Pair(v, id));
                    adj[v].Add(new Pair(u, id));
                    id++;
                }
            }
        }

        int E = id;

        bool foundPath = false;
        bool foundCircuit = false;

        // Try every starting vertex.
        for (int start = 0; start < V; start++) {
            bool[] used = new bool[E];
            bool isCircuit = false;

            if (dfs(start, start, 0, E, adj, used,
                    ref isCircuit)) {
                foundPath = true;

                if (isCircuit)
                    foundCircuit = true;
            }
        }

        if (foundCircuit)
            return 2;
        if (foundPath)
            return 1;
        return 0;
    }

    static void Main()
    {
        int V = 3;

        int[][] adj
            = { new int[] { 1, 2 }, new int[] { 0, 2 },
                new int[] { 0, 1 } };

        Console.WriteLine(isEulerCircuit(V, adj));
    }
}
JavaScript
function dfs(u, start, usedEdges, totalEdges, adj, used,
             isCircuit)
{
    if (usedEdges === totalEdges) {
        if (u === start) {
            isCircuit[0] = true;
        }
        return true;
    }

    for (let [v, id] of adj[u]) {
        if (!used[id]) {
            used[id] = true;

            if (dfs(v, start, usedEdges + 1, totalEdges,
                    adj, used, isCircuit)) {
                return true;
            }

            used[id] = false;
        }
    }

    return false;
}

function isEulerCircuit(V, graph)
{
    let adj = Array.from({length : V}, () => []);
    let id = 0;

    // Assign a unique id to every undirected edge.
    for (let u = 0; u < V; u++) {
        for (let v of graph[u]) {
            if (u < v) {
                adj[u].push([ v, id ]);
                adj[v].push([ u, id ]);
                id++;
            }
        }
    }

    let E = id;

    let foundPath = false;
    let foundCircuit = false;

    // Try every starting vertex.
    for (let start = 0; start < V; start++) {
        let used = new Array(E).fill(false);
        let isCircuit = [ false ];

        if (dfs(start, start, 0, E, adj, used, isCircuit)) {
            foundPath = true;

            if (isCircuit[0]) {
                foundCircuit = true;
            }
        }
    }

    if (foundCircuit) {
        return 2;
    }
    if (foundPath) {
        return 1;
    }
    return 0;
}

// Driver Code
let V = 3;
let adj = [ [ 1, 2 ], [ 0, 2 ], [ 0, 1 ] ];

console.log(isEulerCircuit(V, adj));

Output
2

[Expected Approach] Check Connectivity and Count Odd Degree Vertices - O(V + E) Time and O(V) Space

A graph has an Eulerian Path if and only if the below two conditions are true

All vertices with non-zero degree must belong to the same connected component. (We ignore isolated vertices as they do not affect the cycle.)

Exactly Zero or Two Vertices with Odd Degree:

  • If zero vertices have odd degree -> Eulerian Cycle exists (which is also a path).
  • If two vertices have odd degree -> Eulerian Path exists (but not a cycle).
  • If one vertex has odd degree -> Not possible in an undirected graph. (Because the sum of all degrees in an undirected graph is always even.)

Note: A graph with no edges is trivially Eulerian. There are no edges to traverse, so by definition, it satisfies both Eulerian Path and Cycle conditions.

How Does This Work? 

  • In an Eulerian Path, whenever we enter a vertex (except start and end), we must also leave it. So all intermediate vertices must have even degree.
  • In an Eulerian Cycle, since we start and end at the same vertex, every vertex must have even degree. This ensures that every entry into a vertex can be paired with an exit.

Working of the Approach:

  • Find a vertex having a non-zero degree and start a DFS from it.
  • Mark all reachable vertices during the DFS traversal.
  • Check if every vertex with a non-zero degree has been visited. If not, return 0 since the graph is disconnected.
  • Count the number of vertices having an odd degree.
  • If the odd-degree count is 0, return 2 (Euler Circuit).
  • If the odd-degree count is 2, return 1 (Euler Path).
  • Otherwise, return 0 (Neither Euler Path nor Euler Circuit).

Let us understand with an example:
Input: adj = [[1, 2], [0, 2], [0, 1]]

  • Start DFS from the first vertex with a non-zero degree (0) and visit all reachable vertices (0 → 1 → 2).
  • Since every vertex with a non-zero degree is visited, the graph is connected.
  • Count the degree of each vertex: deg(0) = 2, deg(1) = 2, and deg(2) = 2, so all have even degree.
  • The number of odd-degree vertices is 0.
  • Therefore, the graph contains an Euler Circuit, and the function returns 2.
C++
#include <bits/stdc++.h>
using namespace std;

// Performs DFS traversal from the given vertex.
void dfsUtil(int u, vector<bool> &vis, vector<vector<int>> &adj)
{
    vis[u] = true;

    for (auto v : adj[u])
    {
        if (!vis[v])
            dfsUtil(v, vis, adj);
    }
}

// Checks whether all vertices with non-zero degree
// belong to the same connected component.
bool isConnected(int V, vector<vector<int>> &adj)
{
    vector<bool> vis(V, false);

    // Find the first vertex having a non-zero degree.
    int i;
    for (i = 0; i < V; i++)
    {
        if (adj[i].size() > 0)
            break;
    }

    // Graph has no edges.
    if (i == V)
        return true;

    // Traverse all reachable vertices.
    dfsUtil(i, vis, adj);

    // Check whether all non-zero degree vertices are visited.
    for (i = 0; i < V; i++)
    {
        if (!vis[i] && adj[i].size() > 0)
            return false;
    }

    return true;
}

int isEulerCircuit(int V, vector<vector<int>> &adj)
{
    // Graph must be connected.
    if (!isConnected(V, adj))
        return 0;

    int odd = 0;

    // Count the vertices having odd degree.
    for (int i = 0; i < V; i++)
    {
        if (adj[i].size() & 1)
            odd++;
    }

    // More than two odd-degree vertices.
    if (odd > 2)
        return 0;

    // Return 2 for Euler Circuit and 1 for Euler Path.
    return odd ? 1 : 2;
}

int main()
{
    int V = 3;
    vector<vector<int>> adj(V);

    // Add undirected edges:
    // 0 - 1
    // |  /
    // 2
    adj[0] = {1, 2};
    adj[1] = {0, 2};
    adj[2] = {0, 1};

    cout << isEulerCircuit(V, adj);

    return 0;
}
Java
import java.util.*;

public class GFG {

    // Performs DFS traversal from the given vertex.
    static void dfsUtil(int u, boolean[] vis, int[][] adj)
    {
        vis[u] = true;

        for (int v : adj[u]) {
            if (!vis[v])
                dfsUtil(v, vis, adj);
        }
    }

    // Checks whether all vertices with non-zero degree
    // belong to the same connected component.
    static boolean isConnected(int V, int[][] adj)
    {

        boolean[] vis = new boolean[V];

        // Find the first vertex having a non-zero degree.
        int i;
        for (i = 0; i < V; i++) {
            if (adj[i].length > 0)
                break;
        }

        // Graph has no edges.
        if (i == V)
            return true;

        // Traverse all reachable vertices.
        dfsUtil(i, vis, adj);

        // Check whether all non-zero degree vertices are
        // visited.
        for (i = 0; i < V; i++) {
            if (!vis[i] && adj[i].length > 0)
                return false;
        }

        return true;
    }

    static int isEulerCircuit(int V, int[][] adj)
    {

        // Graph must be connected.
        if (!isConnected(V, adj))
            return 0;

        int odd = 0;

        // Count the vertices having odd degree.
        for (int i = 0; i < V; i++) {
            if ((adj[i].length & 1) == 1)
                odd++;
        }

        // More than two odd-degree vertices.
        if (odd > 2)
            return 0;

        // Return 2 for Euler Circuit and 1 for Euler Path.
        return odd != 0 ? 1 : 2;
    }

    public static void main(String[] args)
    {

        int V = 3;

        // Add undirected edges:
        // 0 - 1
        // |  /
        // 2
        int[][] adj = { { 1, 2 }, { 0, 2 }, { 0, 1 } };

        System.out.println(isEulerCircuit(V, adj));
    }
}
Python
# Performs DFS traversal from the given vertex.
def dfsUtil(u, vis, adj):
    vis[u] = True

    for v in adj[u]:
        if not vis[v]:
            dfsUtil(v, vis, adj)

# Checks whether all vertices with non-zero degree
# belong to the same connected component.


def isConnected(V, adj):
    vis = [False] * V

    # Find the first vertex having a non-zero degree.
    for i in range(V):
        if len(adj[i]) > 0:
            break

    # Graph has no edges.
    if i == V:
        return True

    # Traverse all reachable vertices.
    dfsUtil(i, vis, adj)

    # Check whether all non-zero degree vertices are visited.
    for i in range(V):
        if not vis[i] and len(adj[i]) > 0:
            return False

    return True


def isEulerCircuit(V, adj):
    # Graph must be connected.
    if not isConnected(V, adj):
        return 0

    odd = 0

    # Count the vertices having odd degree.
    for i in range(V):
        if len(adj[i]) % 2 != 0:
            odd += 1

    # More than two odd-degree vertices.
    if odd > 2:
        return 0

    # Return 2 for Euler Circuit and 1 for Euler Path.
    return 1 if odd else 2


if __name__ == "__main__":
    V = 3
    adj = [[] for _ in range(V)]

    # Add undirected edges:
    # 0 - 1
    # |  /
    # 2
    adj[0].extend([1, 2])
    adj[1].extend([0, 2])
    adj[2].extend([0, 1])

    print(isEulerCircuit(V, adj))
C#
using System;

class GFG {
    // Performs DFS traversal from the given vertex.
    static void dfsUtil(int u, bool[] vis, int[][] adj)
    {
        vis[u] = true;

        foreach(int v in adj[u])
        {
            if (!vis[v])
                dfsUtil(v, vis, adj);
        }
    }

    // Checks whether all vertices with non-zero degree
    // belong to the same connected component.
    static bool isConnected(int V, int[][] adj)
    {
        bool[] vis = new bool[V];

        // Find the first vertex having a non-zero degree.
        int i;
        for (i = 0; i < V; i++) {
            if (adj[i].Length > 0)
                break;
        }

        // Graph has no edges.
        if (i == V)
            return true;

        // Traverse all reachable vertices.
        dfsUtil(i, vis, adj);

        // Check whether all non-zero degree vertices are
        // visited.
        for (i = 0; i < V; i++) {
            if (!vis[i] && adj[i].Length > 0)
                return false;
        }

        return true;
    }

    static int isEulerCircuit(int V, int[][] adj)
    {
        // Graph must be connected.
        if (!isConnected(V, adj))
            return 0;

        int odd = 0;

        // Count the vertices having odd degree.
        for (int i = 0; i < V; i++) {
            if ((adj[i].Length & 1) == 1)
                odd++;
        }

        // More than two odd-degree vertices.
        if (odd > 2)
            return 0;

        // Return 2 for Euler Circuit and 1 for Euler Path.
        return odd != 0 ? 1 : 2;
    }

    static void Main()
    {
        int V = 3;

        // Add undirected edges:
        // 0 - 1
        // |  /
        // 2
        int[][] adj
            = { new int[] { 1, 2 }, new int[] { 0, 2 },
                new int[] { 0, 1 } };

        Console.WriteLine(isEulerCircuit(V, adj));
    }
}
JavaScript
// Performs DFS traversal from the given vertex.
function dfsUtil(u, vis, adj)
{

    vis[u] = true;

    for (const v of adj[u]) {
        if (!vis[v])
            dfsUtil(v, vis, adj);
    }
}

// Checks whether all vertices with non-zero degree
// belong to the same connected component.
function isConnected(V, adj)
{

    let vis = new Array(V).fill(false);

    // Find the first vertex having a non-zero degree.
    let i;
    for (i = 0; i < V; i++) {
        if (adj[i].length > 0)
            break;
    }

    // Graph has no edges.
    if (i === V)
        return true;

    // Traverse all reachable vertices.
    dfsUtil(i, vis, adj);

    // Check whether all non-zero degree vertices are
    // visited.
    for (i = 0; i < V; i++) {
        if (!vis[i] && adj[i].length > 0)
            return false;
    }

    return true;
}

function isEulerCircuit(V, adj)
{

    // Graph must be connected.
    if (!isConnected(V, adj))
        return 0;

    let odd = 0;

    // Count the vertices having odd degree.
    for (let i = 0; i < V; i++) {
        if (adj[i].length & 1)
            odd++;
    }

    // More than two odd-degree vertices.
    if (odd > 2)
        return 0;

    // Return 2 for Euler Circuit and 1 for Euler Path.
    return odd ? 1 : 2;
}

// Driver code

let V = 3;

// Add undirected edges:
// 0 - 1
// |  /
// 2
let adj = [ [ 1, 2 ], [ 0, 2 ], [ 0, 1 ] ];

console.log(isEulerCircuit(V, adj));

Output
2
Comment