From 5206954959608fca3504e0e5a71b3bbbf0f8124c Mon Sep 17 00:00:00 2001 From: Rounak Choudhary Date: Thu, 5 Mar 2026 00:04:33 +0530 Subject: [PATCH] docs: correct Euler path/cycle conditions and Hierholzer complexity --- ...HeirHolzer_algo_for_Euler_Cycle_or_Path.md | 76 +++++++++++++++---- 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/Graph/Connectivity/HeirHolzer_algo_for_Euler_Cycle_or_Path.md b/Graph/Connectivity/HeirHolzer_algo_for_Euler_Cycle_or_Path.md index 003dbc3..0e2c629 100644 --- a/Graph/Connectivity/HeirHolzer_algo_for_Euler_Cycle_or_Path.md +++ b/Graph/Connectivity/HeirHolzer_algo_for_Euler_Cycle_or_Path.md @@ -1,16 +1,27 @@ **Condition for Euler path or cycle in directed graph is** - -* Indegree[u] == outdegree[u], for atleast n-2 vertices -* All vertices with non-zero indegree(or outdegree) should be part of same SCC (isolated vertices which doesnt contribute any edge maybe there) +* Let `in[u]=indegree(u)` and `out[u]=outdegree(u)`. Isolated vertices with `in[u]+out[u]==0` can be ignored. +* **Euler cycle (directed)** exists iff: + * `in[u]==out[u]` for all vertices `u` + * All vertices with `in[u]+out[u]>0` belong to the same SCC (strongly connected after ignoring isolated vertices) +* **Euler path (directed)** exists iff: + * Exactly one vertex `s` has `out[s]=in[s]+1` (start vertex) + * Exactly one vertex `t` has `in[t]=out[t]+1` (end vertex) + * For all other vertices `u`, `in[u]==out[u]` + * All vertices with `in[u]+out[u]>0` belong to the same weakly connected component (connected if directions are ignored) **Condition for Euler path or cycle in undirected graph is** - -* All vertices should have even degree, atleast n-2 vertices. -* All vertices with non-zero degree should be connected ( isolated vertices which doesnt contribute any edge maybe there) +* Isolated vertices with `deg[u]==0` can be ignored. +* All vertices with non-zero degree should be connected. +* Following cases arise - + * If number of odd degree vertices is greater than 2 then no euler path or cycle + * If no odd degree vertices then there exist a Euler cycle. + * If odd degree vertices are 2 then there exist a Euler path. **HeirHolzer algorithm for finding Euler path or cycle whichever exist** - -* Time Complexity = `O(m + nlogn)` for undirected graph, have to use vector of multiset to represent adjacency list -* Time Complexity = `O(m)` for directed graph -* Time Complexity = `O(m + n*n)` for adjacency matrix representation -* Following cases arise - +* Time Complexity = `O(m)` if adjacency list is stored as `vector>` (or list) with pointer/iterator per node (no log deletions) +* Time Complexity = `O(m log n)` if you use `vector>` (because each erase/find is `log`) +* Time Complexity = `O(n*n)` for adjacency matrix representation (matrix scan based implementation) +* Undirected graph handling - * If number of odd degree vertices is greater than 2 then no euler path or cycle * If no odd degree vertices then there exist a Euler cycle. * If odd degree vertices are 2 then there exist a Euler path. In this case **add an edge between odd vertices** and find euler cycle. See note below to further handle this case @@ -18,14 +29,16 @@ **NOTE** - In result array which we obtain from finding euler cycle, `result[0] == result.back()` **Code Description** - -* Push any node in stack +* Push a valid start node in stack: + * If odd degree vertices are 2, start from an odd vertex + * Else start from any vertex with non-zero degree (if all are zero then answer is trivial) * While stack is not empty * u = st.top(); * if `adj[u].size() == 0, push u to result array` and pop stack * else: * `v = adj[u].begin(); push v to stack` * remove v from adj[u] and remove u from adj[v] (in case of undirected graph) -* Result array will contain the euler cycle, with `result[0] == result.back()` +* Result array will contain the euler cycle (often in reverse order of traversal), with `result[0] == result.back()` for a cycle **NOTE** - * If we added an edge to handle odd degree vertices then to print euler path do this - @@ -33,6 +46,7 @@ * Find index result array such that `result[i] == v1 && result[i+1] == v2 or vice versa`, let call that index `id` * `print result from (id + 1 to result.size() - 1)` * `print result from (1 to id)` +* Also ensure you started Hierholzer from a non-zero degree vertex (or odd vertex in path case), otherwise the algorithm may not traverse the component containing edges. ```c++ #include @@ -75,14 +89,32 @@ void solve(int test) cout<<"No euler path or cycle"<0){start=i;break;} + } + } + stacks; - s.push(0); + s.push(start); vectorres; while(!s.empty()) @@ -98,7 +130,12 @@ void solve(int test) { int v = *adj[u].begin(); adj[u].erase(adj[u].begin()); - auto it = adj[v].find(u); // first find one iterator pointing to u. Because simply calling multiset.erase(value) removes all instances of that value. + auto it = adj[v].find(u); + if(it==adj[v].end()) + { + cout<<"Invalid edge state"<path; int id = -1; - for(i=0;i