Camino Euleriano en grafo no dirigido

Dada una representación matricial de adyacencia de un grafo no dirigido. Encuentra si hay algún Camino Euleriano en el gráfico. Si no hay ruta, imprima «Sin solución». Si hay alguna ruta, imprima la ruta. 

Ejemplos: 

Input : [[0, 1, 0, 0, 1],
         [1, 0, 1, 1, 0],
         [0, 1, 0, 1, 0],
         [0, 1, 1, 0, 0],
         [1, 0, 0, 0, 0]]

Output : 5 -> 1 -> 2 -> 4 -> 3 -> 2

Input : [[0, 1, 0, 1, 1],
         [1, 0, 1, 0, 1],
         [0, 1, 0, 1, 1],
         [1, 1, 1, 0, 0],
         [1, 0, 1, 0, 0]]
Output : "No Solution"

El caso base de este problema es que si el número de vértices con un número impar de aristas (es decir, grado impar) es mayor que 2, entonces no hay un camino euleriano. 
Si tiene la solución y todos los Nodes tienen un número par de aristas entonces podemos iniciar nuestro camino desde cualquiera de los Nodes. 
Si tiene la solución y exactamente dos vértices tienen un número impar de aristas entonces tenemos que empezar nuestro camino desde uno de estos dos vértices. 
No se dará el caso de que exactamente un vértice tenga un número impar de aristas, ya que hay un número par de aristas en total.

Proceso para encontrar el camino:  

  1. Primero, toma una pila vacía y un camino vacío.
  2. Si todos los vértices tienen un número par de aristas, comience desde cualquiera de ellos. Si dos de los vértices tienen un número impar de aristas, comienza desde uno de ellos. Establezca la corriente variable en este vértice inicial.
  3. Si el vértice actual tiene al menos un Node adyacente, primero descubra ese Node y luego descubra el Node actual retrocediendo. Para hacerlo, agregue el Node actual a la pila, elimine el borde entre el Node actual y el Node vecino, establezca actual en el Node vecino.
  4. Si el Node actual no tiene ningún vecino, agréguelo a la ruta y coloque la pila actual en el vértice emergente.
  5. Repita los procesos 3 y 4 hasta que la pila esté vacía y el Node actual no tenga ningún vecino.

Eulerian Path in undirected graph

Después de la variable de la ruta del proceso, se encuentra la ruta Euleriana.

C++

// Efficient C++ program to
// find out Eulerian path
#include <bits/stdc++.h>
using namespace std;
 
// Function to find out the path
// It takes the adjacency matrix
// representation of the graph as input
void findpath(int graph[][5], int n)
{
    vector<int> numofadj;
 
    // Find out number of edges each vertex has
    for (int i = 0; i < n; i++)
        numofadj.push_back(accumulate(graph[i],
                                      graph[i] + 5, 0));
 
    // Find out how many vertex has odd number edges
    int startpoint = 0, numofodd = 0;
    for (int i = n - 1; i >= 0; i--)
    {
        if (numofadj[i] % 2 == 1)
        {
            numofodd++;
            startpoint = i;
        }
    }
 
    // If number of vertex with odd number of edges
    // is greater than two return "No Solution".
    if (numofodd > 2)
    {
        cout << "No Solution" << endl;
        return;
    }
 
    // If there is a path find the path
    // Initialize empty stack and path
    // take the starting current as discussed
    stack<int> stack;
    vector<int> path;
    int cur = startpoint;
 
    // Loop will run until there is element in the stack
    // or current edge has some neighbour.
    while (!stack.empty() or
            accumulate(graph[cur],
                       graph[cur] + 5, 0) != 0)
    {
        // If current node has not any neighbour
        // add it to path and pop stack
        // set new current to the popped element
        if (accumulate(graph[cur],
                       graph[cur] + 5, 0) == 0)
        {
            path.push_back(cur);
            cur = stack.top();
            stack.pop();
        }
 
        // If the current vertex has at least one
        // neighbour add the current vertex to stack,
        // remove the edge between them and set the
        // current to its neighbour.
        else
        {
            for (int i = 0; i < n; i++)
            {
                if (graph[cur][i] == 1)
                {
                    stack.push(cur);
                    graph[cur][i] = 0;
                    graph[i][cur] = 0;
                    cur = i;
                    break;
                }
            }
        }
    }
 
    // print the path
    for (auto ele : path) cout << ele << " -> ";
    cout << cur << endl;
}
 
// Driver Code
int main()
{
    // Test case 1
    int graph1[][5] = {{0, 1, 0, 0, 1},
                       {1, 0, 1, 1, 0},
                       {0, 1, 0, 1, 0},
                       {0, 1, 1, 0, 0},
                       {1, 0, 0, 0, 0}};
    int n = sizeof(graph1) / sizeof(graph1[0]);
    findpath(graph1, n);
 
    // Test case 2
    int graph2[][5] = {{0, 1, 0, 1, 1},
                       {1, 0, 1, 0, 1},
                       {0, 1, 0, 1, 1},
                       {1, 1, 1, 0, 0},
                       {1, 0, 1, 0, 0}};
    n = sizeof(graph1) / sizeof(graph1[0]);
    findpath(graph2, n);
 
    // Test case 3
    int graph3[][5] = {{0, 1, 0, 0, 1},
                       {1, 0, 1, 1, 1},
                       {0, 1, 0, 1, 0},
                       {0, 1, 1, 0, 1},
                       {1, 1, 0, 1, 0}};
    n = sizeof(graph1) / sizeof(graph1[0]);
    findpath(graph3, n);
}
 
// This code is contributed by
// sanjeev2552

Java

// Efficient Java program to
// find out Eulerian path
import java.util.*;
 
class GFG
{
 
    // Function to find out the path
    // It takes the adjacency matrix
    // representation of the graph as input
    static void findpath(int[][] graph, int n)
    {
        Vector<Integer> numofadj = new Vector<>();
 
        // Find out number of edges each vertex has
        for (int i = 0; i < n; i++)
            numofadj.add(accumulate(graph[i], 0));
 
        // Find out how many vertex has odd number edges
        int startPoint = 0, numofodd = 0;
        for (int i = n - 1; i >= 0; i--)
        {
            if (numofadj.elementAt(i) % 2 == 1)
            {
                numofodd++;
                startPoint = i;
            }
        }
 
        // If number of vertex with odd number of edges
        // is greater than two return "No Solution".
        if (numofodd > 2)
        {
            System.out.println("No Solution");
            return;
        }
 
        // If there is a path find the path
        // Initialize empty stack and path
        // take the starting current as discussed
        Stack<Integer> stack = new Stack<>();
        Vector<Integer> path = new Vector<>();
        int cur = startPoint;
 
        // Loop will run until there is element in the stack
        // or current edge has some neighbour.
        while (!stack.isEmpty() || accumulate(graph[cur], 0) != 0)
        {
 
            // If current node has not any neighbour
            // add it to path and pop stack
            // set new current to the popped element
            if (accumulate(graph[cur], 0) == 0)
            {
                path.add(cur);
                cur = stack.pop();
 
                // If the current vertex has at least one
                // neighbour add the current vertex to stack,
                // remove the edge between them and set the
                // current to its neighbour.
            }
            else
            {
                for (int i = 0; i < n; i++)
                {
                    if (graph[cur][i] == 1)
                    {
                        stack.add(cur);
                        graph[cur][i] = 0;
                        graph[i][cur] = 0;
                        cur = i;
                        break;
                    }
                }
            }
        }
 
        // print the path
        for (int ele : path)
            System.out.print(ele + " -> ");
        System.out.println(cur);
    }
 
    static int accumulate(int[] arr, int sum)
    {
        for (int i : arr)
            sum += i;
        return sum;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
 
        // Test case 1
        int[][] graph1 = { { 0, 1, 0, 0, 1 },
                        { 1, 0, 1, 1, 0 },
                        { 0, 1, 0, 1, 0 },
                        { 0, 1, 1, 0, 0 },
                        { 1, 0, 0, 0, 0 } };
        int n = graph1.length;
        findpath(graph1, n);
 
        // Test case 2
        int[][] graph2 = { { 0, 1, 0, 1, 1 },
                        { 1, 0, 1, 0, 1 },
                        { 0, 1, 0, 1, 1 },
                        { 1, 1, 1, 0, 0 },
                        { 1, 0, 1, 0, 0 } };
        n = graph2.length;
        findpath(graph2, n);
 
        // Test case 3
        int[][] graph3 = { { 0, 1, 0, 0, 1 },
                        { 1, 0, 1, 1, 1 },
                        { 0, 1, 0, 1, 0 },
                        { 0, 1, 1, 0, 1 },
                        { 1, 1, 0, 1, 0 } };
        n = graph3.length;
        findpath(graph3, n);
    }
}
 
// This code is contributed by
// sanjeev2552

Python3

# Efficient Python3 program to
# find out Eulerian path
 
# Function to find out the path
# It takes the adjacency matrix
# representation of the graph as input
def findpath(graph, n):
     
    numofadj = []
 
    # Find out number of edges each
    # vertex has
    for i in range(n):
        numofadj.append(sum(graph[i]))
 
    # Find out how many vertex has
    # odd number edges
    startpoint, numofodd = 0, 0
    for i in range(n - 1, -1, -1):
        if (numofadj[i] % 2 == 1):
            numofodd += 1
            startpoint = i
 
    # If number of vertex with odd number of edges
    # is greater than two return "No Solution".
    if (numofodd > 2):
        print("No Solution")
        return
 
    # If there is a path find the path
    # Initialize empty stack and path
    # take the starting current as discussed
    stack = []
    path = []
    cur = startpoint
 
    # Loop will run until there is element in the
    # stack or current edge has some neighbour.
    while (len(stack) > 0 or sum(graph[cur])!= 0):
         
        # If current node has not any neighbour
        # add it to path and pop stack set new
        # current to the popped element
        if (sum(graph[cur]) == 0):
            path.append(cur)
            cur = stack[-1]
            del stack[-1]
 
        # If the current vertex has at least one
        # neighbour add the current vertex to stack,
        # remove the edge between them and set the
        # current to its neighbour.
        else:
            for i in range(n):
                if (graph[cur][i] == 1):
                    stack.append(cur)
                    graph[cur][i] = 0
                    graph[i][cur] = 0
                    cur = i
                    break
 
    # Print the path
    for ele in path:
        print(ele, end = " -> ")
         
    print(cur)
 
# Driver Code
if __name__ == '__main__':
     
    # Test case 1
    graph1 = [ [ 0, 1, 0, 0, 1 ],
               [ 1, 0, 1, 1, 0 ],
               [ 0, 1, 0, 1, 0 ],
               [ 0, 1, 1, 0, 0 ],
               [ 1, 0, 0, 0, 0 ] ]
    n = len(graph1)
    findpath(graph1, n)
 
    # Test case 2
    graph2 = [ [ 0, 1, 0, 1, 1 ],
               [ 1, 0, 1, 0, 1 ],
               [ 0, 1, 0, 1, 1 ],
               [ 1, 1, 1, 0, 0 ],
               [ 1, 0, 1, 0, 0 ] ]
    n = len(graph2)
    findpath(graph2, n)
 
    # Test case 3
    graph3 = [ [ 0, 1, 0, 0, 1 ],
               [ 1, 0, 1, 1, 1 ],
               [ 0, 1, 0, 1, 0 ],
               [ 0, 1, 1, 0, 1 ],
               [ 1, 1, 0, 1, 0 ] ]
    n = len(graph3)
    findpath(graph3, n)
 
# This code is contributed by mohit kumar 29

C#

// Efficient C# program to
// find out Eulerian path
using System;
using System.Collections.Generic;
class GFG{
 
// Function to find out the path
// It takes the adjacency matrix
// representation of the graph
// as input
static void findpath(int[,] graph,
                     int n)
{
  List<int> numofadj =
            new List<int>();
 
  // Find out number of edges
  // each vertex has
  for (int i = 0; i < n; i++)
    numofadj.Add(accumulate(graph,
                            i, 0));
 
  // Find out how many vertex has
  // odd number edges
  int startPoint = 0, numofodd = 0;
  for (int i = n - 1; i >= 0; i--)
  {
    if (numofadj[i] % 2 == 1)
    {
      numofodd++;
      startPoint = i;
    }
  }
 
  // If number of vertex with odd
  // number of edges is greater than
  // two return "No Solution".
  if (numofodd > 2)
  {
    Console.WriteLine("No Solution");
    return;
  }
 
  // If there is a path find the path
  // Initialize empty stack and path
  // take the starting current as
  // discussed
  Stack<int> stack = new Stack<int>();
  List<int> path = new List<int>();
  int cur = startPoint;
 
  // Loop will run until there is element
  // in the stack or current edge has some
  // neighbour.
  while (stack.Count != 0 ||
         accumulate(graph, cur, 0) != 0)
  {
 
    // If current node has not any
    // neighbour add it to path and
    // pop stack set new current to
    // the popped element
    if (accumulate(graph,cur, 0) == 0)
    {
      path.Add(cur);
      cur = stack.Pop();
 
      // If the current vertex has at
      // least one neighbour add the
      // current vertex to stack, remove
      // the edge between them and set the
      // current to its neighbour.
    }
    else
    {
      for (int i = 0; i < n; i++)
      {
        if (graph[cur, i] == 1)
        {
          stack.Push(cur);
          graph[cur, i] = 0;
          graph[i, cur] = 0;
          cur = i;
          break;
        }
      }
    }
  }
 
  // print the path
  foreach (int ele in path)
    Console.Write(ele + " -> ");
  Console.WriteLine(cur);
}
 
static int accumulate(int[,] matrix,
                      int row, int sum)
{   
  int []arr = GetRow(matrix,
                     row);
   
 foreach (int i in arr)
   sum += i;
 return sum;
}
   
public static int[] GetRow(int[,] matrix,
                           int row)
{
  var rowLength = matrix.GetLength(1);
  var rowVector = new int[rowLength];
 
  for (var i = 0; i < rowLength; i++)
    rowVector[i] = matrix[row, i];
 
  return rowVector;
}
   
// Driver Code
public static void Main(String[] args)
{
  // Test case 1
  int[,] graph1 = {{0, 1, 0, 0, 1},
                   {1, 0, 1, 1, 0},
                   {0, 1, 0, 1, 0},
                   {0, 1, 1, 0, 0},
                   {1, 0, 0, 0, 0}};
  int n = graph1.GetLength(0);
  findpath(graph1, n);
 
  // Test case 2
  int[,] graph2 = {{0, 1, 0, 1, 1},
                   {1, 0, 1, 0, 1},
                   {0, 1, 0, 1, 1},
                   {1, 1, 1, 0, 0},
                   {1, 0, 1, 0, 0}};
  n = graph2.GetLength(0);
  findpath(graph2, n);
 
  // Test case 3
  int[,] graph3 = {{0, 1, 0, 0, 1},
                   {1, 0, 1, 1, 1},
                   {0, 1, 0, 1, 0},
                   {0, 1, 1, 0, 1},
                   {1, 1, 0, 1, 0}};
  n = graph3.GetLength(0);
  findpath(graph3, n);
}
}
 
// This code is contributed by Rajput-Ji

Javascript

<script>
 
// Efficient JavaScript program to
// find out Eulerian path
 
// Function to find out the path
// It takes the adjacency matrix
// representation of the graph as input
 
function sum(a){
    let Sum = 0
    for(let x of a)
        Sum += x
    return Sum
}
 
function findpath(graph, n){
     
    let numofadj = []
 
    // Find out number of edges each
    // vertex has
    for(let i=0;i<n;i++)
        numofadj.push(sum(graph[i]))
 
    // Find out how many vertex has
    // odd number edges
    let startpoint = 0, numofodd = 0
    for(let i=n-1;i>=0;i--){
        if (numofadj[i] % 2 == 1){
            numofodd += 1
            startpoint = i
        }
    }
 
    // If number of vertex with odd number of edges
    // is greater than two return "No Solution".
    if (numofodd > 2){
        document.write("No Solution","</br>")
        return
    }
 
    // If there is a path find the path
    // Initialize empty stack and path
    // take the starting current as discussed
    let stack = []
    let path = []
    let cur = startpoint
 
    // Loop will run until there is element in the
    // stack or current edge has some neighbour.
    while (stack.length > 0 || sum(graph[cur])!= 0){
         
        // If current node has not any neighbour
        // add it to path and pop stack set new
        // current to the popped element
        if (sum(graph[cur]) == 0){
            path.push(cur)
            cur = stack.pop()
        }
 
        // If the current vertex has at least one
        // neighbour add the current vertex to stack,
        // remove the edge between them and set the
        // current to its neighbour.
        else{
            for(let i=0;i<n;i++){
                if (graph[cur][i] == 1){
                    stack.push(cur)
                    graph[cur][i] = 0
                    graph[i][cur] = 0
                    cur = i
                    break
                }
            }
        }
    }
    // Print the path
    for(let ele of path)
        document.write(ele," -> ")
         
    document.write(cur,"</br>")
}
 
// Driver Code
     
// Test case 1
 
let graph1 = [ [ 0, 1, 0, 0, 1 ],
            [ 1, 0, 1, 1, 0 ],
            [ 0, 1, 0, 1, 0 ],
            [ 0, 1, 1, 0, 0 ],
            [ 1, 0, 0, 0, 0 ] ]
let n = graph1.length
findpath(graph1, n)
 
// Test case 2
let graph2 = [ [ 0, 1, 0, 1, 1 ],
            [ 1, 0, 1, 0, 1 ],
            [ 0, 1, 0, 1, 1 ],
            [ 1, 1, 1, 0, 0 ],
            [ 1, 0, 1, 0, 0 ] ]
n = graph2.length
findpath(graph2, n)
 
// Test case 3
let graph3 = [ [ 0, 1, 0, 0, 1 ],
            [ 1, 0, 1, 1, 1 ],
            [ 0, 1, 0, 1, 0 ],
            [ 0, 1, 1, 0, 1 ],
            [ 1, 1, 0, 1, 0 ] ]
n = graph3.length
findpath(graph3, n)
 
// This code is contributed by shinjanpatra
 
</script>

Producción: 

4 -> 0 -> 1 -> 3 -> 2 -> 1
No Solution
4 -> 3 -> 2 -> 1 -> 4 -> 0 -> 1 -> 3

Complejidad de tiempo: 
La complejidad de tiempo de ejecución de este algoritmo es O(E). Este algoritmo también se puede utilizar para encontrar el circuito euleriano. Si el primer y el último vértice del camino son iguales, entonces será un circuito euleriano.

Publicación traducida automáticamente

Artículo escrito por egoista y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *