Académique Documents
Professionnel Documents
Culture Documents
Informalmente se define como G = (V, E), siendo los elementos de V los vértices, y los
elementos de E, las aristas (edges en inglés). Formalmente, un grafo, G, se define como un
par ordenado, G = (V, E), donde V es un conjunto finito y E es un conjunto que consta de
dos elementos de V.
Índice
1 Formas de representación
2 Especificación de los tipos abstractos de datos de un grafo no dirigido
o 2.1 Generadores
o 2.2 Constructores
o 2.3 Selectores
3 Enlaces externos
Formas de representación
Existen diferentes implementaciones del tipo grafo: con una matriz de adyacencias (forma
acotada) y con listas y multilistas de adyacencia (no acotadas).
Matriz de adyacencias: se asocia cada fila y cada columna a cada nodo del grafo,
siendo los elementos de la matriz la relación entre los mismos, tomando los valores
de 1 si existe la arista y 0 en caso contrario.
Joseph Kruskal
Saltar a: navegación, búsqueda
Índice
1 Biografía
2 Familia
3 Referencias
4 Enlaces externos
Biografía
Investigador del Math Center (Bell-Labs), en 1956 descubrió un algoritmo para la
resolución del problema del árbol recubridor mínimo, el cual es un problema típico de
optimización combinatoria, que fue considerado originalmente por Otakar Boruvka (1926)
mientras estudiaba la necesidad de electrificación rural en el sur de Moravia en
Checoslovaquia.
El objetivo del algoritmo de Kruskal es construir un árbol (subgrafo sin ciclos) formado por
arcos sucesivamente seleccionados de mínimo peso a partir de un grafo con pesos en los
arcos.
Un árbol (spanning tree) de un grafo es un subgrafo que contiene todos sus vértices o
nodos. Un grafo puede tener múltiples árboles. Por ejemplo, un grafo completo de cuatro
nodos (todos relacionados con todos) tendría 16 árboles.
La aplicación típica de este problema es el diseño de redes telefónicas. Una empresa con
diferentes oficinas, trata de trazar líneas de teléfono para conectarlas unas con otras. La
compañía telefónica le ofrece esta interconexión, pero ofrece tarifas diferentes o costes por
conectar cada par de oficinas. Cómo conectar entonces las oficinas al mínimo coste total.
La formulación del MST también ha sido aplicada para hallar soluciones en diversas áreas
(diseño de redes de transporte, diseño de redes de telecomunicaciones - TV por cable,
sistemas distribuidos, interpretación de datos climatológicos, visión artificial - análisis de
imágenes - extracción de rasgos de parentesco, análisis de clusters y búsqueda de
superestructuras de quasar, plegamiento de proteínas, reconocimiento de células
cancerosas, y otros).
Otra aplicación menos obvia es que el árbol de coste total mínimo puede ser usado como
solución aproximada al problema del viajante de comercio, el cual es NP-completo. La
manera formal de definir este problema es encontrar la trayectoria más corta para visitar
cada punto al menos una vez. Nótese que si se visitan todos los puntos exactamente una
vez, lo que se tiene es un tipo especial de árbol. En el ejemplo anterior, 12 de los 16 árboles
son trayectorias de este tipo. Si se tiene una trayectoria que visita algunos vértices más de
una vez, siempre se puede soltar algunos nodos del árbol. En general el peso del árbol total
mínimo es menor que el del viajante de comercio, debido a que su minimización se realiza
sobre un conjunto estrictamente mayor. Existen diferentes algoritmos y maneras de usar el
árbol de coste total mínimo para encontrar la solución al problema del viajante de comercio
(con resultados cercanos al óptimo).
Lista de adyacencias: se asocia a cada nodo del grafo una lista que contenga todos
aquellos nodos que sean adyacentes a él.
Añadir una arista: Dado un grafo, añade una relación entre dos nodos de dicho grafo.
Añadir un nodo: Dado un grafo, incluye un nodo en él, en caso en el que no exista
previamente.
Constructores
Borrar nodo: Devuelve un grafo sin un nodo y las aristas relacionadas con él. Si dicho nodo
no existe se devuelve el grafo inicial.
Borrar arista: Devuelve un grafo sin la arista indicada. En caso de que la arista no exista
devuelve el grafo inicial.
Selectores
Adyacentes: Comprueba si dos nodos tienen una arista que los relacione.
Algoritmo de Kruskal
Saltar a: navegación, búsqueda
Un ejemplo de árbol expandido mínimo. Cada punto representa un vértice, el cual puede ser
un árbol por sí mismo. Se usa el Algoritmo para buscar las distancias más cortas (árbol
expandido) que conectan todos los puntos o vértices.
se crea un bosque B (un conjunto de árboles), donde cada vértice del grafo es un
árbol separado
se crea un conjunto C que contenga a todas las aristas del grafo
mientras C es no vacío
o eliminar una arista de peso mínimo de C
o si esa arista conecta dos árboles diferentes se añade al bosque, combinando
los dos árboles en un solo árbol
o en caso contrario, se desecha la arista
Este algoritmo fue publicado por primera vez en Proceedings of the American
Mathematical Society, pp. 48–50 en 1956, y fue escrito por Joseph Kruskal.
Índice
1 Pseudocódigo
2 Código en C++
3 Complejidad del algoritmo
4 Demostración de la correctitud
5 Ejemplo
6 Referencias
7 Enlaces externos
Pseudocódigo
function Kruskal(G)
Para cada v en V[G] hacer
Nuevo conjunto C(v) ← {v}.
Nuevo heap Q que contiene todas las aristas de G, ordenando por su
peso.
Defino un arbol T ← Ø
// n es el número total de vértices
Mientras T tenga menos de n-1 vertices hacer
(u,v) ← Q.sacarMin()
// previene ciclos en T. agrega (u,v) si u y v están diferentes
componentes en el conjunto.
// Nótese que C(u) devuelve la componente a la que pertenece u.
if C(v) ≠ C(u) then
Agregar arista (v,u) to T.
Merge C(v) y C(u) en el conjunto
Return arbol T
Código en C++
// Declaraciones en el archivo .h
int cn; //cantidad de nodos
vector< vector<int> > ady; //matriz de adyacencia
int nodoA;
int nodoB;
int arcos = 1;
while(arcos < cn){
// Encontrar el arco mínimo que no forma ciclo y guardar los
nodos y la distancia.
int min = INF;
for(int i = 0; i < cn; i++)
for(int j = 0; j < cn; j++)
if(min > adyacencia[i][j] && pertenece[i] !=
pertenece[j]){
min = adyacencia[i][j];
nodoA = i;
nodoB = j;
}
arcos++;
}
}
return arbol;
}
Se puede conseguir esta complejidad de la siguiente manera: primero se ordenan las aristas
por su peso usando una ordenación por comparación (comparison sort) con una
complejidad del orden de O(m log m); esto permite que el paso "eliminar una arista de peso
mínimo de C" se ejecute en tiempo constante. Lo siguiente es usar una estructura de datos
sobre conjuntos disjuntos (disjoint-set data structure) para controlar qué vértices están en
qué componentes. Es necesario hacer orden de O(m) operaciones ya que por cada arista hay
dos operaciones de búsqueda y posiblemente una unión de conjuntos. Incluso una
estructura de datos sobre conjuntos disjuntos simple con uniones por rangos puede ejecutar
las operaciones mencionadas en O(m log n). Por tanto, la complejidad total es del orden de
O(m log m) = O(m log n).
Con la condición de que las aristas estén ordenadas o puedan ser ordenadas en un tiempo
lineal (por ejemplo, mediante el ordenamiento por cuentas o con el ordenamiento Radix), el
algoritmo puede usar estructuras de datos de conjuntos disjuntos más complejas para
ejecutarse en tiempos del orden de O(m α(n)), donde α es la inversa (tiene un crecimiento
extremadamente lento) de la función de Ackermann.
Demostración de la correctitud
Sea P un grafo conexo y valuado y sea Y el subgrafo de P producido por el algoritmo. Y no
puede tener ciclos porque cada vez que se añade una arista, ésta debe conectar vértices de
dos árboles diferentes y no vértices dentro de un subárbol. Y no puede ser disconexa ya que
la primera arista que une dos componentes de Y debería haber sido añadida por el
algoritmo. Por tanto, Y es un árbol expandido de P.
Sea Y1 el árbol expandido de peso mínimo de P, el cual tiene el mayor número de aristas en
común con Y. Si Y1=Y entonces Y es un árbol de expansión mínimo. Por otro lado, sea e la
primera arista considerada por el algoritmo que está en Y y que no está en Y1. Sean C1 y C2
las componentes de P que conecta la arista e. Ya que Y1 es un árbol, Y1+e tiene un ciclo y
existe una arista diferente f en ese ciclo que también conecta C1 y C2. Entonces Y2=Y1+e-f
es también un árbol expandido. Ya que e fue considerada por el algoritmo antes que f, el
peso de e es al menos igual que que el peso de f y ya que Y1 es un árbol expandido mínimo,
los pesos de esas dos aristas deben ser de hecho iguales. Por tanto, Y2 es un árbol expandido
mínimo con más aristas en común con Y que las que tiene Y1, contradiciendo las hipótesis
que se habían establecido antes para Y1. Esto prueba que Y debe ser un árbol expandido de
peso mínimo.
Otros algoritmos para este problema son el algoritmo de Prim y el algoritmo de Boruvka.
Ejemplo