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:
Output: 2 Explanation: Following is an eulerian circuit in the mentioned graph: 1 -> 2 -> 0 -> 1
Input:
Output: 1 Explanation: Following is an eulerian path in the mentioned graph: 1 -> 0 -> 2
[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>usingnamespacestd;// Tries to traverse all edges exactly once.booldfs(intu,intstart,intusedEdges,inttotalEdges,vector<vector<pair<int,int>>>&adj,vector<bool>&used,bool&isCircuit){if(usedEdges==totalEdges){if(u==start)isCircuit=true;returntrue;}for(auto[v,id]:adj[u]){if(!used[id]){used[id]=true;if(dfs(v,start,usedEdges+1,totalEdges,adj,used,isCircuit))returntrue;used[id]=false;}}returnfalse;}intisEulerCircuit(intV,vector<vector<int>>&graph){vector<vector<pair<int,int>>>adj(V);intid=0;// Assign a unique id to every undirected edge.for(intu=0;u<V;u++){for(intv:graph[u]){if(u<v){adj[u].push_back({v,id});adj[v].push_back({u,id});id++;}}}intE=id;boolfoundPath=false;boolfoundCircuit=false;// Try every starting vertex.for(intstart=0;start<V;start++){vector<bool>used(E,false);boolisCircuit=false;if(dfs(start,start,0,E,adj,used,isCircuit)){foundPath=true;if(isCircuit)foundCircuit=true;}}if(foundCircuit)return2;if(foundPath)return1;return0;}intmain(){intV=3;vector<vector<int>>adj(V);// Add undirected edges:// 0 - 1// | /// 2adj[0]={1,2};adj[1]={0,2};adj[2]={0,1};cout<<isEulerCircuit(V,adj);return0;}
Java
importjava.util.*;classPair{intv,id;Pair(intv,intid){this.v=v;this.id=id;}}publicclassGFG{// Tries to traverse all edges exactly once.staticbooleandfs(intu,intstart,intusedEdges,inttotalEdges,ArrayList<ArrayList<Pair>>adj,boolean[]used,boolean[]isCircuit){if(usedEdges==totalEdges){if(u==start)isCircuit[0]=true;returntrue;}for(Pairp:adj.get(u)){if(!used[p.id]){used[p.id]=true;if(dfs(p.v,start,usedEdges+1,totalEdges,adj,used,isCircuit))returntrue;used[p.id]=false;}}returnfalse;}staticintisEulerCircuit(intV,int[][]graph){ArrayList<ArrayList<Pair>>adj=newArrayList<>();for(inti=0;i<V;i++)adj.add(newArrayList<>());intid=0;// Assign a unique id to every undirected edge.for(intu=0;u<V;u++){for(intv:graph[u]){if(u<v){adj.get(u).add(newPair(v,id));adj.get(v).add(newPair(u,id));id++;}}}intE=id;booleanfoundPath=false;booleanfoundCircuit=false;// Try every starting vertex.for(intstart=0;start<V;start++){boolean[]used=newboolean[E];boolean[]isCircuit=newboolean[1];if(dfs(start,start,0,E,adj,used,isCircuit)){foundPath=true;if(isCircuit[0])foundCircuit=true;}}if(foundCircuit)return2;if(foundPath)return1;return0;}publicstaticvoidmain(String[]args){intV=3;int[][]adj={{1,2},{0,2},{0,1}};System.out.println(isEulerCircuit(V,adj));}}
Python
# Tries to traverse all edges exactly once.defdfs(u,start,usedEdges,totalEdges,adj,used,isCircuit):ifusedEdges==totalEdges:ifu==start:isCircuit[0]=TruereturnTrueforv,edgeIdinadj[u]:ifnotused[edgeId]:used[edgeId]=Trueifdfs(v,start,usedEdges+1,totalEdges,adj,used,isCircuit):returnTrueused[edgeId]=FalsereturnFalsedefisEulerCircuit(V,graph):adj=[[]for_inrange(V)]edgeId=0# Assign a unique id to every undirected edge.foruinrange(V):forvingraph[u]:ifu<v:adj[u].append((v,edgeId))adj[v].append((u,edgeId))edgeId+=1E=edgeIdfoundPath=FalsefoundCircuit=False# Try every starting vertex.forstartinrange(V):used=[False]*EisCircuit=[False]ifdfs(start,start,0,E,adj,used,isCircuit):foundPath=TrueifisCircuit[0]:foundCircuit=TrueiffoundCircuit:return2iffoundPath:return1return0if__name__=="__main__":V=3# Add undirected edges:# 0 - 1# | /# 2adj=[[1,2],[0,2],[0,1]]print(isEulerCircuit(V,adj))
C#
usingSystem;usingSystem.Collections.Generic;classPair{publicintv,id;publicPair(intv,intid){this.v=v;this.id=id;}}classGFG{// Tries to traverse all edges exactly once.staticbooldfs(intu,intstart,intusedEdges,inttotalEdges,List<List<Pair>>adj,bool[]used,refboolisCircuit){if(usedEdges==totalEdges){if(u==start)isCircuit=true;returntrue;}foreach(Pairpinadj[u]){if(!used[p.id]){used[p.id]=true;if(dfs(p.v,start,usedEdges+1,totalEdges,adj,used,refisCircuit))returntrue;used[p.id]=false;}}returnfalse;}staticintisEulerCircuit(intV,int[][]graph){List<List<Pair>>adj=newList<List<Pair>>();for(inti=0;i<V;i++)adj.Add(newList<Pair>());intid=0;// Assign a unique id to every undirected edge.for(intu=0;u<V;u++){foreach(intvingraph[u]){if(u<v){adj[u].Add(newPair(v,id));adj[v].Add(newPair(u,id));id++;}}}intE=id;boolfoundPath=false;boolfoundCircuit=false;// Try every starting vertex.for(intstart=0;start<V;start++){bool[]used=newbool[E];boolisCircuit=false;if(dfs(start,start,0,E,adj,used,refisCircuit)){foundPath=true;if(isCircuit)foundCircuit=true;}}if(foundCircuit)return2;if(foundPath)return1;return0;}staticvoidMain(){intV=3;int[][]adj={newint[]{1,2},newint[]{0,2},newint[]{0,1}};Console.WriteLine(isEulerCircuit(V,adj));}}
JavaScript
functiondfs(u,start,usedEdges,totalEdges,adj,used,isCircuit){if(usedEdges===totalEdges){if(u===start){isCircuit[0]=true;}returntrue;}for(let[v,id]ofadj[u]){if(!used[id]){used[id]=true;if(dfs(v,start,usedEdges+1,totalEdges,adj,used,isCircuit)){returntrue;}used[id]=false;}}returnfalse;}functionisEulerCircuit(V,graph){letadj=Array.from({length:V},()=>[]);letid=0;// Assign a unique id to every undirected edge.for(letu=0;u<V;u++){for(letvofgraph[u]){if(u<v){adj[u].push([v,id]);adj[v].push([u,id]);id++;}}}letE=id;letfoundPath=false;letfoundCircuit=false;// Try every starting vertex.for(letstart=0;start<V;start++){letused=newArray(E).fill(false);letisCircuit=[false];if(dfs(start,start,0,E,adj,used,isCircuit)){foundPath=true;if(isCircuit[0]){foundCircuit=true;}}}if(foundCircuit){return2;}if(foundPath){return1;}return0;}// Driver CodeletV=3;letadj=[[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>usingnamespacestd;// Performs DFS traversal from the given vertex.voiddfsUtil(intu,vector<bool>&vis,vector<vector<int>>&adj){vis[u]=true;for(autov:adj[u]){if(!vis[v])dfsUtil(v,vis,adj);}}// Checks whether all vertices with non-zero degree// belong to the same connected component.boolisConnected(intV,vector<vector<int>>&adj){vector<bool>vis(V,false);// Find the first vertex having a non-zero degree.inti;for(i=0;i<V;i++){if(adj[i].size()>0)break;}// Graph has no edges.if(i==V)returntrue;// 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)returnfalse;}returntrue;}intisEulerCircuit(intV,vector<vector<int>>&adj){// Graph must be connected.if(!isConnected(V,adj))return0;intodd=0;// Count the vertices having odd degree.for(inti=0;i<V;i++){if(adj[i].size()&1)odd++;}// More than two odd-degree vertices.if(odd>2)return0;// Return 2 for Euler Circuit and 1 for Euler Path.returnodd?1:2;}intmain(){intV=3;vector<vector<int>>adj(V);// Add undirected edges:// 0 - 1// | /// 2adj[0]={1,2};adj[1]={0,2};adj[2]={0,1};cout<<isEulerCircuit(V,adj);return0;}
Java
importjava.util.*;publicclassGFG{// Performs DFS traversal from the given vertex.staticvoiddfsUtil(intu,boolean[]vis,int[][]adj){vis[u]=true;for(intv:adj[u]){if(!vis[v])dfsUtil(v,vis,adj);}}// Checks whether all vertices with non-zero degree// belong to the same connected component.staticbooleanisConnected(intV,int[][]adj){boolean[]vis=newboolean[V];// Find the first vertex having a non-zero degree.inti;for(i=0;i<V;i++){if(adj[i].length>0)break;}// Graph has no edges.if(i==V)returntrue;// 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)returnfalse;}returntrue;}staticintisEulerCircuit(intV,int[][]adj){// Graph must be connected.if(!isConnected(V,adj))return0;intodd=0;// Count the vertices having odd degree.for(inti=0;i<V;i++){if((adj[i].length&1)==1)odd++;}// More than two odd-degree vertices.if(odd>2)return0;// Return 2 for Euler Circuit and 1 for Euler Path.returnodd!=0?1:2;}publicstaticvoidmain(String[]args){intV=3;// Add undirected edges:// 0 - 1// | /// 2int[][]adj={{1,2},{0,2},{0,1}};System.out.println(isEulerCircuit(V,adj));}}
Python
# Performs DFS traversal from the given vertex.defdfsUtil(u,vis,adj):vis[u]=Trueforvinadj[u]:ifnotvis[v]:dfsUtil(v,vis,adj)# Checks whether all vertices with non-zero degree# belong to the same connected component.defisConnected(V,adj):vis=[False]*V# Find the first vertex having a non-zero degree.foriinrange(V):iflen(adj[i])>0:break# Graph has no edges.ifi==V:returnTrue# Traverse all reachable vertices.dfsUtil(i,vis,adj)# Check whether all non-zero degree vertices are visited.foriinrange(V):ifnotvis[i]andlen(adj[i])>0:returnFalsereturnTruedefisEulerCircuit(V,adj):# Graph must be connected.ifnotisConnected(V,adj):return0odd=0# Count the vertices having odd degree.foriinrange(V):iflen(adj[i])%2!=0:odd+=1# More than two odd-degree vertices.ifodd>2:return0# Return 2 for Euler Circuit and 1 for Euler Path.return1ifoddelse2if__name__=="__main__":V=3adj=[[]for_inrange(V)]# Add undirected edges:# 0 - 1# | /# 2adj[0].extend([1,2])adj[1].extend([0,2])adj[2].extend([0,1])print(isEulerCircuit(V,adj))
C#
usingSystem;classGFG{// Performs DFS traversal from the given vertex.staticvoiddfsUtil(intu,bool[]vis,int[][]adj){vis[u]=true;foreach(intvinadj[u]){if(!vis[v])dfsUtil(v,vis,adj);}}// Checks whether all vertices with non-zero degree// belong to the same connected component.staticboolisConnected(intV,int[][]adj){bool[]vis=newbool[V];// Find the first vertex having a non-zero degree.inti;for(i=0;i<V;i++){if(adj[i].Length>0)break;}// Graph has no edges.if(i==V)returntrue;// 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)returnfalse;}returntrue;}staticintisEulerCircuit(intV,int[][]adj){// Graph must be connected.if(!isConnected(V,adj))return0;intodd=0;// Count the vertices having odd degree.for(inti=0;i<V;i++){if((adj[i].Length&1)==1)odd++;}// More than two odd-degree vertices.if(odd>2)return0;// Return 2 for Euler Circuit and 1 for Euler Path.returnodd!=0?1:2;}staticvoidMain(){intV=3;// Add undirected edges:// 0 - 1// | /// 2int[][]adj={newint[]{1,2},newint[]{0,2},newint[]{0,1}};Console.WriteLine(isEulerCircuit(V,adj));}}
JavaScript
// Performs DFS traversal from the given vertex.functiondfsUtil(u,vis,adj){vis[u]=true;for(constvofadj[u]){if(!vis[v])dfsUtil(v,vis,adj);}}// Checks whether all vertices with non-zero degree// belong to the same connected component.functionisConnected(V,adj){letvis=newArray(V).fill(false);// Find the first vertex having a non-zero degree.leti;for(i=0;i<V;i++){if(adj[i].length>0)break;}// Graph has no edges.if(i===V)returntrue;// 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)returnfalse;}returntrue;}functionisEulerCircuit(V,adj){// Graph must be connected.if(!isConnected(V,adj))return0;letodd=0;// Count the vertices having odd degree.for(leti=0;i<V;i++){if(adj[i].length&1)odd++;}// More than two odd-degree vertices.if(odd>2)return0;// Return 2 for Euler Circuit and 1 for Euler Path.returnodd?1:2;}// Driver codeletV=3;// Add undirected edges:// 0 - 1// | /// 2letadj=[[1,2],[0,2],[0,1]];console.log(isEulerCircuit(V,adj));