Eulerian path and circuit | GeeksforGeeks


Eulerian path and circuit | GeeksforGeeks
Eulerian Path is a path in graph that visits every edge exactly once. Eulerian Circuit is an Eulerian Path which starts and ends on the same vertex.

通过图(无向图或有向图)中所有边且每边仅通过一次的通路称为欧拉通路,相应的回路称为欧拉回路。具有欧拉回路的图称为欧拉图(Euler Graph),具有欧拉通路而无欧拉回路的图称为半欧拉图。

A graph is called Eulerian if it has an Eulerian Cycle and called Semi-Eulerian if it has an Eulerian Path. The problem seems similar toHamiltonian Path which is NP complete problem for a general graph. Fortunately, we can find whether a given graph has a Eulerian Path or not in polynomial time. In fact, we can find it in O(V+E) time.

Backtracking | Set 6 (Hamiltonian Cycle)

Eulerian Cycle
An undirected graph has Eulerian cycle if following two conditions are true.
….a) All vertices with non-zero degree are connected. We don’t care about vertices with zero degree because they don’t belong to Eulerian Cycle or Path (we only consider all edges).
….b) All vertices have even degree.
Eulerian Path
An undirected graph has Eulerian Path if following two conditions are true.
….a) Same as condition (a) for Eulerian Cycle
….b) If zero or two vertices have odd degree and all other vertices have even degree. Note that only one vertex with odd degree is not possible in an undirected graph (sum of all degrees is always even in an undirected graph)
A graph with no edges is considered Eulerian because there are no edges to traverse.

How does this work? ???
In Eulerian path, each time we visit a vertex v, we walk through two unvisited edges with one end point as v. Therefore, all middle vertices in Eulerian Path must have even degree. For Eulerian Cycle, any vertex can be middle vertex, therefore all vertices must have even degree.

class Graph
{
    private int V;   // No. of vertices
    // Array  of lists for Adjacency List Representation
    private LinkedList<Integer> adj[];
    // Constructor
    Graph(int v)
    {
        V = v;
        adj = new LinkedList[v];
        for (int i=0; i<v; ++i)
            adj[i] = new LinkedList();
    }
    //Function to add an edge into the graph
    void addEdge(int v, int w)
    {
        adj[v].add(w);// Add w to v's list.
        adj[w].add(v); //The graph is undirected
    }
    // A function used by DFS
    void DFSUtil(int v,boolean visited[])
    {
        // Mark the current node as visited
        visited[v] = true;
        // Recur for all the vertices adjacent to this vertex
        Iterator<Integer> i = adj[v].listIterator();
        while (i.hasNext())
        {
            int n = i.next();
            if (!visited[n])
                DFSUtil(n, visited);
        }
    }
    // Method to check if all non-zero degree vertices are
    // connected. It mainly does DFS traversal starting from
    boolean isConnected()
    {
        // Mark all the vertices as not visited
        boolean visited[] = new boolean[V];
        int i;
        for (i = 0; i < V; i++)
            visited[i] = false;
        // Find a vertex with non-zero degree
        for (i = 0; i < V; i++)
            if (adj[i].size() != 0)
                break;
        // If there are no edges in the graph, return true
        if (i == V)
            return true;
        // Start DFS traversal from a vertex with non-zero degree
        DFSUtil(i, visited);
        // Check if all non-zero degree vertices are visited
        for (i = 0; i < V; i++)
           if (visited[i] == false && adj[i].size() > 0)
                return false;
        return true;
    }
    /* The function returns one of the following values
       0 --> If grpah is not Eulerian
       1 --> If graph has an Euler path (Semi-Eulerian)
       2 --> If graph has an Euler Circuit (Eulerian)  */
    int isEulerian()
    {
        // Check if all non-zero degree vertices are connected
        if (isConnected() == false)
            return 0;
        // Count vertices with odd degree
        int odd = 0;
        for (int i = 0; i < V; i++)
            if (adj[i].size()%2!=0)
                odd++;
        // If count is more than 2, then graph is not Eulerian
        if (odd > 2)
            return 0;
        // If odd count is 2, then semi-eulerian.
        // If odd count is 0, then eulerian
        // Note that odd count can never be 1 for undirected graph
        return (odd==2)? 1 : 2;
    }

void Graph::DFSUtil(int v, bool visited[])
{
    // Mark the current node as visited and print it
    visited[v] = true;
    // Recur for all the vertices adjacent to this vertex
    list<int>::iterator i;
    for (i = adj[v].begin(); i != adj[v].end(); ++i)
        if (!visited[*i])
            DFSUtil(*i, visited);
}
// Method to check if all non-zero degree vertices are connected.
// It mainly does DFS traversal starting from
bool Graph::isConnected()
{
    // Mark all the vertices as not visited
    bool visited[V];
    int i;
    for (i = 0; i < V; i++)
        visited[i] = false;
    // Find a vertex with non-zero degree
    for (i = 0; i < V; i++)
        if (adj[i].size() != 0)
            break;
    // If there are no edges in the graph, return true
    if (i == V)
        return true;
    // Start DFS traversal from a vertex with non-zero degree
    DFSUtil(i, visited);
    // Check if all non-zero degree vertices are visited
    for (i = 0; i < V; i++)
       if (visited[i] == false && adj[i].size() > 0)
            return false;
    return true;
}
/* The function returns one of the following values
   0 --> If grpah is not Eulerian
   1 --> If graph has an Euler path (Semi-Eulerian)
   2 --> If graph has an Euler Circuit (Eulerian)  */
int Graph::isEulerian()
{
    // Check if all non-zero degree vertices are connected
    if (isConnected() == false)
        return 0;
    // Count vertices with odd degree
    int odd = 0;
    for (int i = 0; i < V; i++)
        if (adj[i].size() & 1)
            odd++;
    // If count is more than 2, then graph is not Eulerian
    if (odd > 2)
        return 0;
    // If odd count is 2, then semi-eulerian.
    // If odd count is 0, then eulerian
    // Note that odd count can never be 1 for undirected graph
    return (odd)? 1 : 2;
}

https://reeestart.wordpress.com/2016/06/09/graph-euler-cyclepath/
Euler Cycle is a cycle that visit each EDGE only once. But each vertex could be visited multiple times.
Hamilton Cycle is a cycle that visit each VERTEX only once.
Euler path is a a path in the graph that visits each edge only once.
For example:
1-> 2-> 3-> 4 is an Euler path but not an Euler Cycle.
1-> 2-> 3-> 4-> 1 is an Euler Cycle.
[Directed Graph]
For a directed graph, it has an Euler Cycle IFF
(1). Every vertex with non-zero degree belong to a single strongly connected component.
(2). Every vertex must have the same in-degree and out-degree.
(See Graph – Strongly Connected Component for more details about SCC)
[Undirected Graph]
For a undirected graph, it has an Euler Cycle IFF
(1). Every vertex with non-zero degree belong to a single strongly connected component.
(2). Every vertex must have EVEN number of degrees.
For a undirected graph, it has an Euler Path IFF
(1). Every vertex with non-zero degree belong to a single strongly connected component.
(2). Only 0 or 2 vertices can have ODD number of degrees, other vertices all have even number of degrees.
public class EulerCycle {
  /* Euler Cycle for Directed Graph */
  /*
    Condition:
      1. Every vertex has the same indegree and outdegree
      2. All vertices with non-zero degrees belong to a single strongly connected component
   */
  public static boolean hasEulerCycle_Directed(Map<Integer, Set<Integer>> graph) {
    return isSCC(graph) && hasSameDegree(graph);
  }
  private static boolean isSCC(Map<Integer, Set<Integer>> graph) {
    if (graph == null && graph.isEmpty()) {
      throw new IllegalArgumentException();
    }
    int[] visited = new int[graph.size()];
    dfs(0, visited, graph);
    for (int tmp : visited) {
      if (tmp == 0) {
        return false;
      }
    }
    Arrays.fill(visited, 0);
    dfs(0, visited, reversed(graph));
    for (int tmp : visited) {
      if (tmp == 0) {
        return false;
      }
    }
    return true;
  }
  private static void dfs(int v, int[] visited, Map<Integer, Set<Integer>> graph) {
    if (visited[v] == 1) {
      return;
    }
    visited[v] = 1;
    for (int adj : graph.get(v)) {
      dfs(adj, visited, graph);
    }
  }
  private static Map<Integer, Set<Integer>> reversed(Map<Integer, Set<Integer>> graph) {
    Map<Integer, Set<Integer>> reversedGraph = new HashMap<>();
    for (int v : graph.keySet()) {
      for (int adj : graph.get(v)) {
        reversedGraph.putIfAbsent(adj, new HashSet<>());
        reversedGraph.get(adj).add(v);
      }
    }
    return reversedGraph;
  }
  private static boolean hasSameDegree(Map<Integer, Set<Integer>> graph) {
    Map<Integer, Integer> indegree = new HashMap<>();
    Map<Integer, Integer> outdegree = new HashMap<>();
    for (int v : graph.keySet()) {
      for (int adj : graph.get(v)) {
        indegree.put(adj, indegree.getOrDefault(adj, 0) + 1);
        outdegree.put(v, outdegree.getOrDefault(v, 0) + 1);
      }
    }
    for (int v : indegree.keySet()) {
      if (!outdegree.containsKey(v) || indegree.get(v) != outdegree.get(v)) {
        return false;
      }
    }
    return true;
  }
  /* Euler Cycle for Undirected Graph */
  /*
    Condition:
      1. All vertices with non-zero degree belong to a single strongly connected component
      2. All vertices must have even number of degrees
   */
  public static boolean hasEulerCycle_Undirected(Map<Integer, Set<Integer>> graph) {
    return isSCCUn(graph) && isCycleDegree(graph);
  }
  /* Euler Path for Undirected Graph */
  /*
    Condition:
      1. All vertices with non-zero degree belong to a single strongly connected component
      2. Only 0 or 2 vertices can have odd number of degrees
   */
  public static boolean hasEulerPath_Undirected(Map<Integer, Set<Integer>> graph) {
    return isSCCUn(graph) && isPathDegree(graph);
  }
  private static boolean isSCCUn(Map<Integer, Set<Integer>> graph) {
    int[] visited = new int[graph.size()];
    dfsUn(0, visited, graph);
    for (int v : visited) {
      if (v == 0) {
        return false;
      }
    }
    return true;
  }
  private static void dfsUn(int v, int[] visited, Map<Integer, Set<Integer>> graph) {
    if (visited[v] == 1) {
      return;
    }
    visited[v] = 1;
    for (int adj : graph.get(v)) {
      dfsUn(adj, visited, graph);
    }
  }
  /* All even */
  private static boolean isCycleDegree(Map<Integer, Set<Integer>> graph) {
    int[] degree = new int[graph.size()];
    for (int v : graph.keySet()) {
      degree[v] += graph.get(v).size();
      for (int adj : graph.get(v)) {
        degree[adj]++;
      }
    }
    for (int v : degree) {
      if (v % 2 != 0) {
        return false;
      }
    }
    return true;
  }
  /* Only 0 or 2 odd */
  private static boolean isPathDegree(Map<Integer, Set<Integer>> graph) {
    int[] degree = new int[graph.size()];
    for (int v : graph.keySet()) {
      degree[v] += graph.get(v).size();
      for (int adj : graph.get(v)) {
        degree[adj]++;
      }
    }
    int oddCnt = 0;
    for (int v : degree) {
      if (v % 2 != 0) {
        oddCnt++;
      }
    }
    return oddCnt == 0 || oddCnt == 2;
  }
}

http://www.geeksforgeeks.org/euler-circuit-directed-graph/
How to check if a directed graph is eulerian?
A directed graph has an eulerian cycle if following conditions are true
1) All vertices with nonzero degree belong to a single strongly connected component.
2) In degree and out degree of every vertex is same.
We can detect singly connected component using Kosaraju’s DFS based simple algorithm.
To compare in degree and out degree, we need to store in degree an out degree of every vertex. Out degree can be obtained by size of adjacency list. In degree can be stored by creating an array of size equal to number of vertices.
Time complexity of the above implementation is O(V + E) as Kosaraju’s algorithm takes O(V + E) time. After running Kosaraju’s algorithm we traverse all vertices and compare in degree with out degree which takes O(V) time.
    private int V;   // No. of vertices
    private LinkedList<Integer> adj[];//Adjacency List
    private int in[];           //maintaining in degree
    //Constructor
    Graph(int v)
    {
        V = v;
        adj = new LinkedList[v];
        in = new int[V];
        for (int i=0; i<v; ++i)
        {
            adj[i] = new LinkedList();
            in[i]  = 0;
        }
    }
    //Function to add an edge into the graph
    void addEdge(int v,int w)
    {
        adj[v].add(w);
        in[w]++;
    }
    // A recursive function to print DFS starting from v
    void DFSUtil(int v,Boolean visited[])
    {
        // Mark the current node as visited
        visited[v] = true;
        int n;
        // Recur for all the vertices adjacent to this vertex
        Iterator<Integer> i =adj[v].iterator();
        while (i.hasNext())
        {
            n = i.next();
            if (!visited[n])
                DFSUtil(n,visited);
        }
    }
    // Function that returns reverse (or transpose) of this graph
    Graph getTranspose()
    {
        Graph g = new Graph(V);
        for (int v = 0; v < V; v++)
        {
            // Recur for all the vertices adjacent to this vertex
            Iterator<Integer> i = adj[v].listIterator();
            while (i.hasNext())
            {
                g.adj[i.next()].add(v);
                (g.in[v])++;
            }
        }
        return g;
    }
    // The main function that returns true if graph is strongly
    // connected
    Boolean isSC()
    {
        // Step 1: Mark all the vertices as not visited (For
        // first DFS)
        Boolean visited[] = new Boolean[V];
        for (int i = 0; i < V; i++)
            visited[i] = false;
        // Step 2: Do DFS traversal starting from first vertex.
        DFSUtil(0, visited);
        // If DFS traversal doesn't visit all vertices, then return false.
        for (int i = 0; i < V; i++)
            if (visited[i] == false)
                return false;
        // Step 3: Create a reversed graph
        Graph gr = getTranspose();
        // Step 4: Mark all the vertices as not visited (For second DFS)
        for (int i = 0; i < V; i++)
            visited[i] = false;
        // Step 5: Do DFS for reversed graph starting from first vertex.
        // Staring Vertex must be same starting point of first DFS
        gr.DFSUtil(0, visited);
        // If all vertices are not visited in second DFS, then
        // return false
        for (int i = 0; i < V; i++)
            if (visited[i] == false)
                return false;
        return true;
    }
    /* This function returns true if the directed graph has an eulerian
       cycle, otherwise returns false  */
    Boolean isEulerianCycle()
    {
        // Check if all non-zero degree vertices are connected
        if (isSC() == false)
            return false;
        // Check if in degree and out degree of every vertex is same
        for (int i = 0; i < V; i++)
            if (adj[i].size() != in[i])
                return false;
        return true;
    }

Given an array of strings, find if the strings can be chained to form a circle | GeeksforGeeks
Read full article from Eulerian path and circuit | GeeksforGeeks

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts