Está en la página 1de 5

Ciclo euleriano

Ir a la navegaci�nIr a la b�squeda
En la teor�a de grafos, un camino euleriano es un camino que pasa por cada arista
una y solo una vez. Un ciclo o circuito euleriano es un camino cerrado que recorre
cada arista exactamente una vez. El problema de encontrar dichos caminos fue
discutido por primera vez por Leonhard Euler, en el famoso problema de los puentes
de K�nigsberg.

�ndice
1 Ciclos eulerianos
2 Historia
3 Casos
4 Teorema
5 Propiedades
6 Construcci�n de trayectos y circuitos
6.1 Algoritmo de Fleury
6.1.1 Implementaci�n en C++ del algoritmo de Fleury
6.2 Algoritmo de Hierholzer
7 Contando circuitos eulerianos en d�grafos
8 V�ase tambi�n
9 Referencias
Ciclos eulerianos

Dibujar un sobre abierto, como el de la imagen, sin levantar el l�piz del papel ni
pasar dos veces por el mismo sitio, es posible. En cambio, dibujar el sobre cerrado
(prescindiendo del punto 5 y sus l�neas adyacentes) es imposible.
En la imagen, {\displaystyle C=\{1,2,3,4,6,3,5,4,1\}\,}{\displaystyle C=\
{1,2,3,4,6,3,5,4,1\}\,} es un ciclo euleriano, luego es un grafo euleriano.

Un grafo es una representaci�n, un modelo, compuesto por un n�mero determinado de


v�rtices (nodos) y un n�mero de arcos (aristas) que los relacionan, cada arista o
arco tiene la capacidad de relacionar dos nodos. La palabra ciclo se emplea en
teor�a de grafos para indicar un camino cerrado en un grafo, es decir, en que el
nodo de inicio y el nodo final son el mismo, como contrapartida un camino
hamiltoniano es un camino que recorre todos los v�rtices de un grafo sin pasar dos
veces por el mismo v�rtice. Si el camino es cerrado se dice un ciclo hamiltoniano.

Si un grafo admite un ciclo euleriano, se denomina grafo euleriano.

Historia
Art�culo principal: Problema de los puentes de K�nigsberg
El origen de la teor�a de los ciclos eulerianos fue planteado y resuelto por el
propio Leonhard Euler en 1736 en un problema que tiene el nombre de Siete puentes
de la ciudad de K�nigsberg (Prusia oriental en el siglo XVIII y actualmente,
Kaliningrado, provincia rusa) dando origen a la Teor�a de los grafos.

El problema se enuncia de la siguiente forma: Dos islas en el r�o Pregel, en


K�nigsberg se unen entre ellas y con la tierra firme mediante siete puentes. �Es
posible dar un paseo empezando por una cualquiera de las cuatro partes de tierra
firme, cruzando cada puente una sola vez y volviendo al punto de partida?

Puentes Konigsberg.jpg

Euler enfoc� el problema representando cada parte de tierra por un punto y cada
puente, por una l�nea, uniendo los puntos que se corresponden. Entonces, el
problema anterior se puede trasladar a la siguiente pregunta: �se puede recorrer el
dibujo sin repetir las l�neas?
K�nigsberg graph.svg

Euler demostr� que no era posible puesto que el n�mero de l�neas que inciden en
cada punto no es par (condici�n necesaria para entrar y salir de cada punto, y para
regresar al punto de partida, por caminos distintos en todo momento).

Casos
Dado un grafo conexo (no existen nodos aislados) y no dirigido {\displaystyle
G=(V,E\,)}{\displaystyle G=(V,E\,)}, si {\displaystyle G\,}G\, tiene exactamente
dos v�rtices de grado impar, entonces {\displaystyle G\,}G\, tiene un camino
euleriano no cerrado. En caso de que todos los v�rtices tengan grado par,
{\displaystyle G\,}G\, tiene un ciclo euleriano.

Teorema
Dado {\displaystyle G(V,E\,)}{\displaystyle G(V,E\,)} no orientado y conexo; si
tiene {\displaystyle 2k\,}{\displaystyle 2k\,} nodos de grado impar, entonces
{\displaystyle G\,}G\, puede ser escrito como uni�n de {\displaystyle k\,}k\,
caminos (simples) distintos sobre los arcos y valen las siguientes expresiones:

1) {\displaystyle G\,}G\, es euleriano;


2) {\displaystyle \forall v\in \ V}{\displaystyle \forall v\in \ V} con grado
{\displaystyle (v)\geq 2}{\displaystyle (v)\geq 2} y par.
3) {\displaystyle G=\coprod _{i=1}^{n}C_{i}}{\displaystyle G=\coprod
_{i=1}^{n}C_{i}} todos disjuntos (caminos distintos) en los arcos,
es decir {\displaystyle C_{i}^{E}\cap \;C_{j}^{E}=\emptyset \;}{\displaystyle
C_{i}^{E}\cap \;C_{j}^{E}=\emptyset \;} con {\displaystyle {i\not \neq \;j}}
{\displaystyle {i\not \neq \;j}}
{\displaystyle \forall C_{i}}{\displaystyle \forall C_{i}} va de un nodo de grado
impar a un nodo de grado impar.

Un grafo admite un camino euleriano cuando tiene exactamente dos nodos de grado
impar (conexos a los caminos).

Propiedades
Un grafo conexo y no dirigido se dice que es euleriano si cada v�rtice tiene un
grado par.
Un grafo no dirigido es euleriano si es conexo y si se puede descomponer en uno con
los v�rtices disjuntos.
Si un grafo no dirigido G es euleriano entonces su gr�fo-l�nea L(G) se dice que es
tambi�n euleriano.
Un grafo dirigido es euleriano si es conexo y cada v�rtice tiene grados internos
iguales a los externos.
Un grafo no dirigido se dice que es susceptible de ser recorrido (en ingl�s:
traversable) si es conexo y dos v�rtices en el grafo tienen grado impar.
Construcci�n de trayectos y circuitos
Algoritmo de Fleury
El algoritmo de Fleury es un algoritmo elegante pero ineficiente cuyo origen se
remonta al a�o 1883. Considerando un grafo del que sabemos que todas las l�neas en
la misma componente y al menos dos v�rtices de �ngulo impar. El algoritmo comienza
en el v�rtice del �ngulo impar. En cada paso se elige el siguiente lado que queda
unido al punto anterior por una sola l�nea. Finalmente nos movemos al lado que
queda en el v�rtice sobrante. Al concluir el algoritmo, no quedan lados sin
recorrer, y la secuencia que queda sigue un ciclo Euleriano sin v�rtices de �ngulos
impares. Tambi�n puede quedar un trayecto Euleriano si hay exactamente dos v�rtices
de �ngulo impar. La complejidad correspondiente a este algoritmo es O(n^2), aunque
hace unos a�os, esta fue mejorada hasta alcanzar una complejidad {\displaystyle O(|
E|(\log |E|)^{3}\log \log |E|)}{\displaystyle O(|E|(\log |E|)^{3}\log \log |E|)}
pero sigue siendo todav�a un recorrido m�s lento que otros algoritmos.
Implementaci�n en C++ del algoritmo de Fleury
// Implemetaci�n en c++
#include <iostream>
#include <string.h>
#include <algorithm>
#include <list>
using namespace std;

// Clase para representar el grafo


class Graph
{
private:
int V; // N� de vertices
list<int> *adj; //vector din�mico
public:
// Constructor y destructor
Graph(int V) { this->V = V; adj = new list<int>[V]; }
~Graph() { delete [] adj; }

void addEdge(int u, int v) { adj[u].push_back(v); adj[v].push_back(u); }


void rmvEdge(int u, int v);

void printEulerTour();
void printEulerUtil(int s);

int DFSCount(int v, bool visited[]);

bool isValidNextEdge(int u, int v);


};

void Graph::printEulerTour()
{
int u = 0;
for (int i = 0; i < V; i++)
if (adj[i].size() & 1)
{ u = i; break; }

printEulerUtil(u);
cout << endl;
}

void Graph::printEulerUtil(int u)
{

list<int>::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
int v = *i;

if (v != -1 && isValidNextEdge(u, v))


{
cout << u << "-" << v << " ";
rmvEdge(u, v);
printEulerUtil(v);
}
}
}
bool Graph::isValidNextEdge(int u, int v)
{
int count = 0;
list<int>::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
if (*i != -1)
count++;
if (count == 1)
return true;

bool visited[V];
memset(visited, false, V);
int count1 = DFSCount(u, visited);

rmvEdge(u, v);
memset(visited, false, V);
int count2 = DFSCount(u, visited);

addEdge(u, v);

return (count1 > count2)? false: true;


}

void Graph::rmvEdge(int u, int v)


{
list<int>::iterator iv = find(adj[u].begin(), adj[u].end(), v);
*iv = -1;

list<int>::iterator iu = find(adj[v].begin(), adj[v].end(), u);


*iu = -1;
}

int Graph::DFSCount(int v, bool visited[])


{
// marcamos el actual
visited[v] = true;
int count = 1;

// Metodo recursivo
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (*i != -1 && !visited[*i])
count += DFSCount(*i, visited);

return count;
}

int main()
{
// Ejemplos
Graph g1(4);
g1.addEdge(0, 1);
g1.addEdge(0, 2);
g1.addEdge(1, 2);
g1.addEdge(2, 3);
g1.printEulerTour();

Graph g2(3);
g2.addEdge(0, 1);
g2.addEdge(1, 2);
g2.addEdge(2, 0);
g2.printEulerTour();

Graph g3(5);
g3.addEdge(1, 0);
g3.addEdge(0, 2);
g3.addEdge(2, 1);
g3.addEdge(0, 3);
g3.addEdge(3, 4);
g3.addEdge(3, 2);
g3.addEdge(3, 1);
g3.addEdge(2, 4);
g3.printEulerTour();

return 0;
}
Algoritmo de Hierholzer
El documento recogido en 1873 procedente de Hierholzer, proporciona un m�todo
diferente a la hora de recorrer los ciclos eulerianos de una forma m�s eficiente
que los algoritmos de Fleury. A continuaci�n se mostraran los pasos necesarios para
este algoritmo:

Elegir cualquier v�rtice v para empezar, y seguir el recorrido de una l�nea hasta
llegar de nuevo a v. No es posible dejar de avanzar en cualquier v�rtice que no sea
v, ya que incluso el grado de todos los v�rtices asegura que cuando se realiza una
traza, deben usarse todas las l�neas excepto una, dejando un v�rtice w. El
recorrido formado, puede no cubrir todos los v�rtices y lados en un grafo o traza
inicial.
Mientras que exista un v�rtice u que pertenezca al actual recorrido pero que tenga
lados adyacentes no pertenecientes a la traza, se comienza de nuevo desde u,
siguiendo los lados no usados hasta regresar a u, y unir el recorrido formado
durante esta traza a la anterior.
Usando estas estructuras de datos como doblemente unidas para mantener un conjunto
de lados incidentes no usados en cada v�rtice, una lista de v�rtices del recorrido
actual y mantener el recorrido en s� mismo es necesario buscar un nuevo v�rtice
para el recorrido, y conectar ambos al mismo v�rtice, de manera que la ejecuci�n de
ambos pueda llevarse a cabo de manera conjunta y la complejidad final del algoritmo
sea lineal (O(E)) sobre la cantidad de aristas.

Contando circuitos eulerianos en d�grafos


El n�mero de circuitos eulerianos en los d�grafos puede ser calculado mediante el
teorema denominado en Ingl�s: BEST-theorem, procedente de los nombres de sus
fundadores: de Bruijn, van Aardenne-Ehrenfest, Smith y Tutte.

En dicho teorema se menciona que dado un d�grafo euleriano G := (V, E), el n�mero
ciclos eulerianos no-equivalentes en el grafo es

{\displaystyle C\prod _{v\in V}(\deg ^{+}(v)-1)!}{\displaystyle C\prod _{v\in V}


(\deg ^{+}(v)-1)!}
o equivalentemente

{\displaystyle C\prod _{v\in V}(\deg ^{-}(v)-1)!}{\displaystyle C\prod _{v\in V}


(\deg ^{-}(v)-1)!}
siendo C cualquier cofactor de la matriz laplaciana de G.