Você está na página 1de 78

UNIDAD I GRAFOS 1.

1 INTRODUCCIN A GRAFOS La Teora de Grafos es parte de Matemticas Discreta que tiene un marcado enfoque prctico, aplicado y computacional, adems de un acentuado carcter formativo. El contenido referido a esta temtica se plantea como respuesta a una variada serie de problemas de la vida real (diseo de bloques, flujo de redes, diseo de circuitos, transporte de viajeros, asignaciones horarias o de tareas, programacin, etc.

G1 es un grafo no simple, pues consta de dos lados paralelos e2 y e3 y dos lazos e1 y e4, pues e2 = (V1, V2), e3 = (V1, V2) y e1 es un lazo, pues e1 = (V1, V1) GRAFOS Existen varios tipos de grafos: a) Un GRAFO NO DIRIGIDO G consiste en un conjunto V de vrtices (o nodos) y un conjunto E de aristas (o arcos) tal que cada arista e E se asocia con un par no ordenado de vrtices. Entonces se puede decir que si existe una arista e entre un par de vrtices v y w, esta puede ser igual a: e = ( v, w) o e = ( w, v)

Un grafo esta formado de vrtices y aristas (lados), por lo tanto G = {V, E} Los vrtices del grafo G son: V_1, V_2, V_3, V_4 entonces V = {V_1, V_2, V_3, V_4} Las aristas del grafo son: e_1, e_2, e_3, e_4 entonces E = {e_1, e_2, e_3, e_4} Entonces podemos decir que G = {{V_1, V_2, V_3, V_4}, {e_1, e_2, e_3, e_4}} Como el grafo G no tiene lazos ni lados paralelos entonces es un grafo simple.

Otro ejemplo de grafo no dirigido es el siguiente:

El grafo no dirigido permite que diferentes aristas se asocien con el mismo par de vrtices. Como podemos apreciar todas las aristas que se asocien con el mismo par de vrtices se denomina aristas paralelas, para el grfico serian e1 y e2 pues convergen en los vrtices (V1, V2). Denominamos lazo a aquella arista que inciden en un mismo vrtice para la grafica sera e3, debido a que incide en el vrtice V2; e3 = (V2, V2). Un vrtice como V4 que no incide en ninguna arista se llama vrtice aislado. Un grafo que contiene lazos y aristas paralelas se llama grafo no simple. b) Un GRAFO DIRIGIDO G consiste en un conjunto V de vrtices (o nodos) y un conjunto E de aristas (o arcos) tal que cada arista e E se asocia con un par ordenado de vrtices. Si hay una nica arista e asociada con el par ordenado (v, w) de vrtices, se escribe e = (v, w), que denota una arista de v a w. En la grafica dirigida sus aristas dirigidas se indican por flechas.

La arista e_3 se asocia con el par ordenado de vrtices (V_4,V_3) debido a que tiene como vrtice origen a V_4 y vrtice destino a V_3, y se denota por: e_3 = {V_4, V_3}. No se puede decir que: e_3 = {V_3, V_4} porque la direccin de la arista e_3 no es esa.

c) Un GRAFO PONDERADO G es aquel en donde se muestran los pesos de cada una de sus aristas. Peso es el valor asignado a cada arista. En un grafo ponderado la longitud de una ruta es la suma de los pesos de las aristas en la ruta.

Ejercicio Complete el cuadro, con la longitud de las diferentes rutas del grafo G expuesto arriba.

d) GRAFO COMPLETO sobre n vrtices, denotada por Kn, es la grfica simple con n vrtices en la que hay una arista entre cada par de vrtices distintos.

G de K_4 y tiene solo una arista entre cada par de vrtices. e) GRAFO DE SIMILITUD se refiere a un grafo que tiende a agrupar objetos semejantes en clases, con base en las propiedades de los objetos. En el textos base pagina 323 se muestra un ejercicio sugiero revisarlo.

SUBGRAFOS Se puede obtener de un grafo un subgrafo. Por ejemplo

Sea G = (V, E) una grfica. (V, E) es una subgrfica de G si: a) V V y E E b) Para toda arista e E, si e incide en v y w, entonces v, w V Por lo antes mencionado podemos determinar que G es un subgrafo de G. V = {V_1, V_2, V_3, V_4} E = {e_1, e_2, e_3, e_4, e_5}

V = ,V_1, V_2, V_3- E = ,e_1, e_2, e_5V V E E Por lo tanto G G GRADO DE UN VERTICE () El grado de un vrtice v, (v), es el nmero de aristas que inciden en v.

(V1) = 3 (V2) = 5 (V3) = 4 (V4) = 1 (V5) = 5 (V6) = 2 (V7) = 2 (V8) = 0 1.2 CAMINOS Y CICLOS Camino o trayectoria es el recorrido desde un V0 (vrtice inicial) a Vn (vrtice destino) de longitud n, es una sucesin alternante de n + 1 vrtices y n aristas que comienza en el vrtice V0 y termina en el Vn . Formalmente significa: comience en el vrtice v0; recorra la arista e1 hasta v1; siga por la arista e2 hasta v2, y as sucesivamente. (v_0', e_1', v_1', e_2', v_2', . v_,n - 1}, e_n, v_n)

Donde la arista e_i es incidente sobre los vrtices v_{i - 1- y v_i para i = 1, n.

Ejemplo:

Construyamos un camino en G desde el vrtice 1 hasta el vrtice 2 de longitud 4. Camino o trayectoria de G: (1, e_1, 2, e_2, 3, e_3, 4, e_4, 2) Adems, el mismo camino se puede representar as: (1, 2, 3, 4, 2) En caso de que no se repita ningn vrtice entonces recibe el nombre de camino simple, por ejemplo: (1, 2, 3,4) y (7, 6, 5,2) IMPORTANTE Sean v y w vrtices en un grafo G. Un camino simple o trayectoria de v a w es una ruta de v a w sin vrtices repetidos. Un ciclo (o circuito) es un camino de longitud diferente de cero de v a v sin aristas repetidas. Un ciclo simple es un ciclo de v a v en el que no hay vrtices repetidos, excepto por el inicio y el fin que son iguales a v. Tomando como referencia la grafica anterior, vamos a determinar si tiene caminos simples, ciclo y ciclo simple.

Una vez aprendido las definiciones anteriores y comprendido el ejemplo, pasamos a estudiar lo que son las grficas conexas. Una grafica G es conexa si dados cualesquiera dos vrtices v y w en G existe una trayectoria de v a w. La grafica que se muestra no es conexa por cuanto no existe trayectoria de v_3 a v_5

CICLO DE EULER Y DE HAMILTON CICLO DE EULER Si una grafica G tiene un ciclo de Euler, entonces G es conexa y todo vrtice tiene grado par (2, 4, 6 ).

Ejemplo: Verificar si la siguiente grfica tiene ciclo de Euler.

Observamos que la grafica es conexa, puesto que sus vrtices tienen grado par as: (v1) = (v2) = (v3)= (v5) = 4 (v4) = 6 (v6) = (v7) = 2 Por lo tanto si existe ciclo de Euler el mismo que es: (v6, v4, v7, v5, v1, v3, v4, v1, v2, v5, v4, v2, v3, v6), si se dan cuenta una caracterstica importante de este camino es que ninguna de sus aristas se repiten. IMPORTANTE Si G no tiene aristas entonces tiene un solo vrtice por lo tanto contiene un ciclo de Euler.

1.3 CICLO DE HAMILTON En honor de Hamilton, decimos que un ciclo en una grafica G que contiene cada vrtice en G exactamente una vez, excepto por el vrtice inicial y final que aparece dos veces, recibe el nombre de ciclo hamiltoniano. Ejemplo: Partiendo de la grfica que se muestra trace un camino de (a) a (a) que contenga todos los vrtices sin repetir ninguno.

El camino de Hamilton solicitado sera: (a, f, g, p, q, r, s, t, o, n, m, l, k, j, i, h, b, c, d, e, a). Como pueden observar no se repite vrtice alguno, excepto el inicial y final que es el mismo.

1.4 ALGORITOMOS DE LA RUTA MS CORTA Problema del camino ms corto

Ejemplo de Grafo Ponderado En la Teora de grafos, el problema de los caminos ms cortos es el problema que consiste en encontrar un camino entre dos vrtices (o nodos) de tal manera que la suma de los pesos de las aristas que lo constituyen es mnima. Un ejemplo es encontrar el camino ms rpido para ir de una

ciudad a otra en un mapa. En este caso, los vrtices representan las ciudades, y las aristas las carreteras que las unen, cuya ponderacin viene dada por el tiempo que se emplea en atravesarlas. Introduccin Formalmente, dado un grafo ponderado (que es un conjunto V de vrtices, un conjunto E de aristas y una funcin de variable real ponderada f : E R) y un elemento v V encuentra un camino P de v a v' V, tal que:

es el mnimo entre todos los caminos que conectan v y v'. El problema es tambin conocido como el problema de los caminos ms cortos entre dos nodos, para diferenciarlo de la siguiente generalizacin:

El problema de los caminos ms cortos desde un origen en el cual tenemos que encontrar los caminos ms cortos de un vrtice origen v a todos los dems vrtices del grafo. El problema de los caminos ms cortos con un destino en el cual tenemos que encontrar los caminos ms cortos desde todos los vrtices del grafo a un nico vrtice destino, esto puede ser reducido al problema anterior invirtiendo el orden. El problema de los caminos ms cortos entre todos los pares de vrtices, el cual tenemos que encontrar los caminos ms cortos entre cada par de vrtices (v , v') en el grafo.

Algoritmos Los algoritmos ms importantes para resolver este problema son:


Algoritmo de Dijkstra, resuelve el problema de los caminos ms cortos entre dos vrtices, desde un origen y un nico destino. Algoritmo de Bellman - Ford, resuelve el problema de los caminos ms cortos desde un origen si la ponderacin de las aristas es negativa. Algoritmo de Bsqueda A*, resuelve el problema de los caminos ms cortos entre un par de vrtices usando la heurstica para intentar agilizar la bsqueda. Algoritmo de Floyd - Warshall, resuelve el problema de los caminos ms cortos entre todos los vrtices. Algoritmo de Johnson, resuelve el problema de los caminos ms cortos entre todos los vrtices y puede ser ms rpido que el de Floyd - Warshall en grafos de baja densidad. Teora perturbacional, encuentra en el peor de los casos el camino ms corto a nivel local.

Aplicaciones Los algoritmos de los caminos ms cortos se aplican para encontrar direcciones de forma automtica entre localizaciones fsicas, tales como direcciones en mapas callejeros. Si un algoritmo representa una mquina abstracta no determinista como un grafo, donde los vrtices describen estados, y las aristas posibles transiciones, el algoritmo de los caminos ms cortos se usa para encontrar una secuencia ptima de opciones para llegar a un cierto estado final o para establecer lmites ms bajos en el tiempo, necesario para alcanzar un estado dado. Por ejemplo, si los vrtices representan los estados de un puzzle como el Cubo de Rubik, cada arista dirigida corresponde a un simple movimiento o giro. El algoritmo de los caminos ms cortos se usa para encontrar la solucin que utiliza el mnimo nmero posible de movimientos. En el argot de las telecomunicaciones, a este algoritmo es tambin conocido como el problema del mnimo retraso, y con frecuencia se compara con el problema de los caminos ms anchos. Una aplicacin ms coloquial es la teora de los "Seis grados de separacin", a partir de la cual se intenta encontrar el camino ms corto entre dos personas cualesquiera. Otras aplicaciones incluyen la Investigacin de operaciones, instalaciones y facilidad de diseo, robtica, transporte y VLSI de diseo. Problemas Relacionados El problema de viajante de comercio, es el problema que trata de encontrar el camino ms corto que pasa slo una vez por cada vrtice y regresa al comienzo. A diferencia de los caminos ms cortos, el cual puede ser resuelto en un tiempo polinomial en grafos sin ciclos negativos, este problema es NPcompleto, y como tal, no tiene una resolucin eficiente (ver P=Problema NP). El problema de encontrar el camino ms largo es tambin NP-completo. Anexo:Ejemplo de Algoritmo de Dijkstra

Grafo inicial

Camino mnimo final Hay diferentes algoritmos para hallar un camino de longitud mnima entre dos vrtices de un grafo ponderado. Presentaremos un algoritmo descubierto por el matemtico holands Edsger Dijkstra en 1959. La versin que descubriremos resuelve este problema para grafos ponderados no dirigidos si todos los pesos son positivos. Este algorimo puede adaptarse fcilmente para resolver problemas de caminos de longitud mnima en grafo dirigidos. A este algoritmo se le llama Algoritmo de Dijkstra: Ejemplo El siguiente ejemplo se desarrollar con el fin de encontrar el camino ms corto desde a hasta z:

Leyenda:

Rojo: Aristas y vrtices pertenecientes a la solucin momentnea. Azul: Aristas y vrtices candidatos.

Paso 1

En este primer paso, podemos apreciar que hay tres candidatos: Los vrtices b, c y d. En este caso, hacemos el camino desde el vrtice a, hasta el vrtice d, ya que es el camino ms corto de los tres.jump!!! Solucin momentnea:

Camino: AD Distancia:5

Paso 2

Ahora, vemos que se aade un nuevo candidato, el vrtice e, y el vrtice c, pero esta vez a travs del d. Pero el camino mnimo surge al aadir el vrtice c. Solucin momentnea:

Camino: ADC Distancia:9

Paso 3

En este paso no se aade ningn candidato ms puesto que el ltimo vrtice es el mismo que en el paso anterior. En este caso el camino mnimo hallado es el siguiente: Solucin momentnea:

Camino: ADCB Distancia:11

Paso 4

Como podemos comprobar, se han aadido dos candidatos nuevos, los vrtices f y g, ambos a travs del vrtice b. El mnimo camino hallado en todo el grafo hasta ahora es el siguiente: Solucin momentnea:

Camino: ADCBF Distancia:15

Paso 5

En este antepenltimo paso, se aaden tres vrtices candidatos, los vrtices g, z y e. Este ltimo ya estaba pero en esta ocasin aparece a travs del vrtice f. En este caso el camino mnimo, que cambia un poco con respecto al enterior, es: Solucin momentnea:

Camino: ADCBF Distancia:17

Paso 6

En el penltimo paso, vuelve a aparecer otro candidato: el vrtice z, pero esta vez a travs del vrtice g. De todas formas, el camino mnimo vuelve a cambiar para retomar el camino que vena siguiendo en los pasos anteriores: Solucin momentnea:

Camino: ADCBFE Distancia:18

Paso 7

Por fin, llegamos al ltimo paso, en el que slo se aade un candidato, el vrtice z a travs del e. El camino mnimo y final obtenido es: Solucin Final:

Camino: ADCBFEZ Distancia:23

Algoritmo de Dijkstra

Ejecucin del algoritmo de Dijkstra. El algoritmo de Dijkstra, tambin llamado algoritmo de caminos mnimos, es un algoritmo para la determinacin del camino ms corto dado un vrtice origen al resto de vrtices en un grafo dirigido y

con pesos en cada arista. Su nombre se refiere a Edsger Dijkstra, quien lo describi por primera vez en 1959. La idea subyacente en este algoritmo consiste en ir explorando todos los caminos ms cortos que parten del vrtice origen y que llevan a todos los dems vrtices; cuando se obtiene el camino ms corto desde el vrtice origen, al resto de vrtices que componen el grafo, el algoritmo se detiene. El algoritmo es una especializacin de la bsqueda de costo uniforme, y como tal, no funciona en grafos con aristas de costo negativo (al elegir siempre el nodo con distancia menor, pueden quedar excluidos de la bsqueda nodos que en prximas iteraciones bajaran el costo general del camino al pasar por una arista con costo negativo). Algoritmo Teniendo un grafo dirigido ponderado de N nodos no aislados, sea x el nodo inicial, un vector D de tamao N guardar al final del algoritmo las distancias desde x al resto de los nodos. 1. Inicializar todas las distancias en D con un valor infinito relativo ya que son desconocidas al principio, exceptuando la de x que se debe colocar en 0 debido a que la distancia de x a x sera 0. 2. Sea a = x (tomamos a como nodo actual). 3. Recorremos todos los nodos adyacentes de a, excepto los nodos marcados, llamaremos a estos vi. 4. Si la distancia desde x hasta vi guardada en D es mayor que la distancia desde x hasta a sumada a la distancia desde a hasta vi; esta se sustituye con la segunda nombrada, esto es: si (Di > Da + d(a, vi)) entonces Di = Da + d(a, vi) 5. Marcamos como completo el nodo a. 6. Tomamos como prximo nodo actual el de menor valor en D (puede hacerse almacenando los valores en una cola de prioridad) y volvemos al paso 3 mientras existan nodos no marcados. Una vez terminado al algoritmo, D estar completamente lleno. Complejidad Orden de complejidad del algoritmo: O(|V|2+|E|) = O(|V|2) sin utilizar cola de prioridad, O((|E|+|V|) log |V|) utilizando cola de prioridad (por ejemplo un montculo). Podemos estimar la complejidad computacional del algoritmo de Dijkstra (en trminos de sumas y comparaciones). El algoritmo realiza a lo ms n-1 iteraciones, ya que en cada iteracin se aade un vrtice al conjunto distinguido. Para estimar el nmero total de operaciones basta estimar el nmero de operaciones que se llevan a cabo en cada iteracin. Podemos identificar el vrtice con la menor etiqueta entre los que no estn en Sk realizando n-1 comparaciones o menos. Despus hacemos una suma y una comparacin para actualizar la etiqueta de cada uno de los vrtices que no estn en S k. Por tanto, en cada iteracin se realizan a lo sumo 2(n-1) operaciones, ya que no puede haber ms de

n-1 etiquetas por actualizar en cada iteracin. Como no se realizan ms de n-1 iteraciones, cada una de las cuales supone a lo ms 2(n-1) operaciones, llegamos al siguiente teorema. TEOREMA: El Algoritmo de Dijkstra realiza O(n2) operaciones (sumas y comparaciones) para determinar la longitud del camino ms corto entre dos vrtices de un grafo ponderado simple, conexo y no dirigido con n vrtices. Pseudocdigo

Estructura de datos auxiliar: Q = Estructura de datos Cola de prioridad (se puede implementar con un montculo)

DIJKSTRA (Grafo G, nodo_fuente s) para u V[G] hacer distancia[u] = INFINITO padre[u] = NULL distancia[s] = 0 Encolar (cola, grafo) mientras que cola no es vaca hacer u = extraer_minimo(cola) para v adyacencia[u] hacer si distancia[v] > distancia[u] + peso (u, v) hacer distancia[v] = distancia[u] + peso (u, v) padre[v] = u Otra versin en pseudocdigo sin cola de prioridad funcin Dijkstra (Grafo G, nodo_salida s) //Usaremos un vector para guardar las distancias del nodo salida al resto entero distancia[n] //Inicializamos el vector con distancias iniciales booleano visto[n] //vector de boleanos para controlar los vertices de los que ya tenemos la distancia mnima para cada w V[G] hacer Si (no existe arista entre s y w) entonces distancia[w] = Infinito //puedes marcar la casilla con un -1 por ejemplo Si_no distancia[w] = peso (s, w) fin si fin para distancia[s] = 0 visto[s] = cierto //n es el nmero de vertices que tiene el Grafo mientras que (no_esten_vistos_todos) hacer vertice = coger_el_minimo_del_vector distancia y que no este visto;

visto[vertice] = cierto; para cada w sucesores (G, vertice) hacer si distancia[w]>distancia[vertice]+peso (vertice, w) entonces distancia[w] = distancia[vertice]+peso (vertice, w) fin si fin para fin mientras fin funcin Al final tenemos en el vector distancia en cada posicin la distancia mnima del vertice salida a otro vertice cualquiera. Implementacin C++

#include <cmath> #include <cstring> #include <iostream> using namespace std; int destino, origen, vertices = 0; int *costos = NULL; void dijkstra(int vertices, int origen, int destino, int *costos) { int i, v, cont = 0; int *ant, *tmp; int *z; /* vertices para los cuales se conoce el camino minimo */ double min; double *dist = new double[vertices]; /* vector con los costos de dos caminos */ /* aloca las lineas de la matriz */ ant = new int[vertices]; tmp = new int[vertices]; z = new int[vertices]; for (i = 0; i < vertices; i++) { if (costos[(origen - 1) * vertices + i] !=- 1) { ant[i] = origen - 1; dist[i] = costos[(origen-1)*vertices+i]; } else { ant[i]= -1;

dist[i] = HUGE_VAL; } z[i]=0; } z[origen-1] = 1; dist[origen-1] = 0; /* Bucle principal */ do { /* Encontrando el vertice que debe entrar en z */ min = HUGE_VAL; for (i=0;i<vertices;i++) if (!z[i]) if (dist[i]>=0 && dist[i]<min) { min=dist[i];v=i; } /* Calculando las distancias de los nodos vecinos de z */ if (min != HUGE_VAL && v != destino - 1) { z[v] = 1; for (i = 0; i < vertices; i++) if (!z[i]) { if (costos[v*vertices+i] != -1 && dist[v] + costos[v*vertices+i] < dist[i]) { dist[i] = dist[v] + costos[v*vertices+i]; ant[i] =v; } } } } while (v != destino - 1 && min != HUGE_VAL); /* Muestra el resultado de la bsqueda */ cout << "\tDe " << origen << " para "<<destino<<" \t"; if (min == HUGE_VAL) { cout <<"No Existe\n"; cout <<"\tCoste: \t- \n"; } else { i = destino; i = ant[i-1]; while (i != -1) { // printf("<-%d",i+1); tmp[cont] = i+1;

cont++; i = ant[i]; } for (i = cont; i > 0; i--) { cout<< tmp[i-1]<<" -> "; } cout << destino; cout <<"\n\tCoste: " << dist[destino-1] <<"\n"; } delete (dist); delete (ant); delete (tmp); delete (z); } int menu(void) { int opcion; cout <<" Implementacion del Algoritmo de Dijkstra\n"; cout <<" Menu:\n"; cout <<" >> 1. Crear el grafo\n >> 2. Determinar el menor camino del grafo\n >> 0. Salir del programa\n"; cout <<endl; cout << " Opcion: "; cin>>opcion; while(opcion<0 || opcion>2){ cout<<" Opcion Invalida. Digitela nuevamente: "; cin>>opcion; } return opcion; } void add(void) {

do { cout <<"\nIngrese el numero de vertices ( no minimo de 2 ): "; cin>>vertices; } while (vertices < 2 ); if (!costos) delete(costos);

costos = new int[vertices * vertices];

for (int i = 0; i <= vertices * vertices; i++) costos[i] = -1; cout <<" N Vertices = "<< vertices<<endl; cout <<"Ahora unamos los vertices:\n" ; bool sigo=true; int origen; int destino; while (sigo){ cout << " Escoja el primer vertice de la arista: " <<endl; do{ cin >> origen; if (origen>vertices){ cout << " El numero del vertice debe ser menor de " << vertices<<endl; } }while(origen > vertices);

cout << " Escoja el segundo vertice de la arista: " <<endl; do{ cin >> destino; if (destino>vertices){ cout << " El numero de vertice debe ser menor de " << vertices<<endl; } }while(destino> vertices); int peso=0; cout <<" Peso: " <<endl; cin>>peso; costos[(origen-1) * vertices + destino - 1] = peso; costos[(destino-1) * vertices + origen - 1] = peso;

int seguir=1;

cout << "Desea anadir otra arista? (0 - NO, 1 - SI, por defecto 1): " ; cin >>seguir; sigo = (seguir==1); } } void buscar(void) { int i, j; cout <<" Lista de los Menores Caminos en Grafo Dado: \n"; for (i = 1; i <= vertices; i++) { for (j = 1; j <= vertices; j++) dijkstra(vertices, i,j, costos); cout<<endl; } cout <<"<Presione ENTER para volver al menu principal. \n"; } int main(int argc, char **argv) { int opcion; do { opcion = menu(); switch(opcion) { case 1: add(); break; case 2: buscar(); break; } } while (opcion!= 0); delete(costos); cout<<"\nHasta la proxima...\n\n"; system("pause"); return 0; }

C++ un poco ms simple con arreglos Otra posible implementacin del algoritmo de Dijkstra incluye un arreglo para las distancias. Esto hace la implementacin ms simple, pero no es eficiente en uso de memoria y adems la versin presentada est limitada en el nmero de nodos del grafo. #include <iostream> #include <limits.h> #include <float.h> using namespace std; #define MAXNODOS 500 #define INDEFINIDO -1 // tamao mximo de la red

int N; float dist[MAXNODOS][MAXNODOS]; float minimo[MAXNODOS]; int anterior[MAXNODOS]; bool visitado[MAXNODOS]; bool minimoNodoNoVisitado (int * nodo) { int candidato = -1; for (int n = 0; n < N; n++) { if (!visitado[n] && (minimo[n] < minimo[candidato] || candidato == -1)) { candidato = n; } } *nodo = candidato; return candidato != -1; } void dijkstra (int origen, int destino) { minimo[origen] = 0.0; int nodo; while (minimoNodoNoVisitado(&nodo)) { if (minimo[nodo] == FLT_MAX) return; inaccesibles visitado[nodo] = true; for (int n = 0; n < N; n++) { if (!visitado[n] && distancia[nodo][n] < 1.0) {

// otros vrtices son

float posibleMin = minimo[nodo] + distancia[nodo][n]; if (posibleMin < minimo[n]) { minimo[n] = posibleMin; anterior[n] = nodo; } } } } } void camino_minimo (int inicio, int final) { if (inicio != final) { camino_minimo (inicio, anterior[final]); cout << ", "; } cout << final; } int main(int argc, char **argv) { int M, inicio, final; // inicializar matriz de distancias y camino minimo cin >> N; for (int k = 0; k < N; k++) { anterior[k] = INDEFINIDO; visitado[k] = false; minimo[k] = MAXINT; for (int l = 0; l < N; l++) { camino[k][l] = FLT_MAX; } } // leer distancias en arcos reales cin >> M; for (int k = 0; k < M; k++) { int i, j; cin >> i >> j; cin >> prob[i][j]; } cin >> inicio >> final;

dijkstra(inicio, final); camino_minimo(inicio, final); return 0; } C++ mediante Heaps Otra posible implementacin del algoritmo de Dijkstra es mediante montculos binarios. struct T_Heap{ A monticulo; int num_elem; }; void CrearHeap(T_Heap& heap){ heap.num_elem= 0; for (int i=0;i<MAX_HEAP;i++){ heap.monticulo[i]= NULL; }//for } void Intercambiar(T_Heap& heap, int i, int j){ T_Lista aux; aux= heap.monticulo[i]; heap.monticulo[i]= heap.monticulo[j]; heap.monticulo[j]= aux; } void Meter(T_Heap& heap, const T_Lista& elem){ int k; k= heap.num_elem; heap.monticulo[k]= elem; while(k != 0 || (heap.monticulo[k]->peso > heap.monticulo[((k-1)/ 2)]->peso){ Intercambiar(heap,k,((k-1)/2)); k= (k-1)/2; }//while heap.num_elem++; } void Sacar(T_Heap& heap, int& elem){ int k; elem= heap.monticulo[0];

heap.monticulo[0]= heap.monticulo[heap.num_elem-1]; heap.monticulo[heap.num_elem-1]= NULL; heap.num_elem--; k= 0; while(k<heap.num_elem && (heap.monticulo[k]->peso < heap.monticulo[2*k+1]->peso || heap.monticulo[k]->peso < heap.monticulo[2*k+2]->peso)){ if (heap.monticulo[k] < heap.monticulo[2*k+1]){ Intercambiar(heap,k,2*k+1); k= 2*k+1; }else{ Intercambiar(heap,k,2*k+2); k= 2*k+2; }//if }//while } bool HeapLleno(const T_Heap& heap){ return(heap.num_elem== MAX_HEAP); } bool HeapVacio(const T_Heap& heap){ return(heap.num_elem== 0); } void DestruirHeap(T_Heap& heap){ for (int i=0;i<MAX_HEAP;i++){ heap.monticulo[i]= NULL; }//for heap.num_elem= 0; } Esta es una implementacin del algoritmo de Dijkstra mediante montculos binarios, que es capaz de dar los mejores resultados para que el algoritmo de Johnson sea ms eficiente. La implementacin del algoritmo devuelve un array de elementos precedentes y otro de distancias, mediante el primero se puede seguir el camino de menor coste desde el nodo pasado como argumento a cualquier otro nodo del grafo, y si paralelamente vamos sumando las distancias del otro array, obtenemos el coste total de dichos caminos mnimos. void Dijkstra(const T_Grafo& grafo, int origen, T_Vector& distancias, T_Vector& previos) { T_Vector marcados; T_Heap colap; T_Lista aux; InicializarVector(distancias); // inicializa los elementos a -1 InicializarVector(previos); InicializarVector(marcados);

distancias[origen]= 0; marcados[origen]= 0; CrearHeap(colap); MeterAdyacentes(colap, grafo, origen, marcados); while (!HeapVacio(colap){ aux = Sacar(colap); marcados[aux->origen]= 0; MeterAdyacentes(colap, grafo, aux->origen, marcados); while (aux != NULL){ if (distancias[aux->destino] > (distancias[aux->origen] + aux->peso)){ distancias[aux->destino]= distancias[aux->origen] + aux->peso; padre[aux->destino] = aux->origen; }//if aux= aux->sig; }//while }//while }

1.5 REPRESENTACIN DE GRFICAS Anteriormente analizamos las grficas como un dibujo, pero cuando se requiere analizar una grafica mediante una computadora se necesita de una representacin mas formal. Conoceremos dos formas:

a) MATRIZ DE ADYACENCIA Para formar la matriz, primero elegimos los vrtices siguiendo un orden cualquiera. A continuacin etiquetamos los renglones y las columnas de una matriz con los vrtices ordenados. La entrada en esta matriz es 1 si los vrtices del rengln y la columna son adyacentes y 0 en caso contrario. Llamamos vrtices adyacentes a aquellos vrtices que estn formados por la misma arista. Llamamos aristas adyacentes a aquellas aristas que convergen en un mismo vrtice.

De la grfica que se muestra podemos decir que a y b son vrtices adyacentes puesto que comparten la misma arista, as, tambin a y d. Las aristas adyacentes que convergen en el vrtice a son: la que une a d con a y la que une a b con a. Los invito a analizar los dems vrtices y aristas de la grfica. En la matriz de la grafica expuesta se pueden detectar algunas propiedades de la grfica simple: El grado de un vrtice (c) = 3 en la fila de c hay tres unos (c) = 3 en la de b hay tres unos (c) = 3 en la de e hay tres unos - La matriz permite representar lazos - No permite representar lados paralelos Al elevar al cuadrado la matriz A obtenemos A2 que determina los caminos de longitud (2) que puede trazarse de cada vrtice. Al elevar al cuadrado (A2) obtenemos A4 que determina los caminos de longitud 4 que hay de cada vrtice.

Ejemplos Los caminos de a - a de longitud 2 son: (2) (a, b, a),(a, d, a) Los camino de b - d de longitud 2 son (2): (b, c, d),(b, a, d) Los caminos de c - c de longitud 2 son (3): (c, b, c),(c, d, c),(c, e, c) Los caminos de d - e de longitud 4 son 6: (d, a, d, c, e), (d, c, d, c, e), (d, a, b, c, e), (d, c, e, c, e), (d, c, e, b, e), (d, c, b, c, e) Los caminos de c - d de longitud 4 son 3: (c, e, b, a, d), (c, b, e, c, d), (c, e, b, c, d) Le sugerimos que busque y encuentre algunos otros caminos: a - b longitud 4 (3)

d - e longitud 4 (6)

b) MATRIZ DE INCIDENCIA Los elementos de esta matriz estn dados por la incidencia entre un vrtice y un lado. Cuando existe esta incidencia se adopta 1, caso contrario 0.

Propiedades: - Permite representar lazos y lados paralelos - La columna con nico valor diferente de 0 es un lazo - Las columnas que no son lazos deben tener (2) unos - La valencia de un vrtice es igual a la suma de la fila

1.6 ISOMORFISMO DE GRFICAS Las graficas G1 y G2 son isomorfas si existe una funcin f uno a uno y sobre de los vrtices de G1 a los vrtices de G2 y una funcin g uno a uno y sobre de las aristas de G1 a las aristas de G2, de manera

que una arista e es incidente en v y w en G1 si y solo si la arista g (e) es incidente en f (v) y f (w) en G2. El par de funciones f y g reciben el nombre de isomorfismo de G1 en G2.

El isomorfismo para las graficas G1 y G2 se define por: f(a) = A, f(b) = B, f(c) = C, f(d) = D, f(e) = E Dos graficas simples G1 y G2 son isomorfas si y solo si para cierto orden de sus vrtices las matrices de adyacencia son iguales. La matriz de adyacencia de la grafica G1 es la que se presenta a continuacin.

La matriz de adyacencia de la grafica G2 es la que se presenta a continuacin.

De nuevo observamos que las grficas G1 y G2 son isomorfas.

1.7 GRFICAS PLANAS Una grfica es plana si se puede dibujar en el plano sin que sus aristas se crucen. Ejemplo: Determiwne si la grafica es plana. Si lo es, dibjela de nuevo sin que se crucen las aristas.

Luego de analizar detenidamente la grafica observamos que si la podemos trazar sin que se crucen las aristas, quedando asi:

Ahora vamos a aplicar la frmula para hacer la verificacin correspondiente. Grfica plana conexa con f = 7 caras (A, B, C, D, E), e = 10 aristas y v = 5 vrtices; f = e v + 2 Entonces: f=ev+2 7 = 10 5 + 2 7 = 7 Por lo tanto la grafica es plana.

Adems, es necesario conocer como demostrar que ciertas grficas no son planas: Se dice que una grfica es plana si se puede dibujar en el plano sin que sus aristas se crucen, si y solo si No contiene una subgrfica homeomorfa a K5 o K3,3 (teorema de Kuratwski). Dos graficas G1 y G2 son homeomorfas si G1 y G2 se pueden reducir a graficas isomorfas realizando varias reducciones en serie. Existe isomorfismo de graficas cuando las figuras G1 y G2 definen las mismas graficas aunque parezcan diferentes. Entonces se puede decir que para que exista isomorfismo se debe tener el mismo nmero de vrtices, de aristas, adems, de que el grado de 2, luego de realizar una reduccin de serie. La reduccin en serie se da cuando en una grafica G las aristas (v, v1) y (v, v2) estn en serie, y al hacer reduccin en serie desaparece v y solo queda v1, v2. Apyese del ejemplo planteado en la pgina 361 del texto base, para su mejor comprensin, utilizando el teorema de Kuratowski.

1.8 ALGORITMOS PARA USO GRAFOS:

Algoritmos importantes

Algoritmo de bsqueda en anchura (BFS) Algoritmo de bsqueda en profundidad (DFS) Algoritmo de bsqueda A* Algoritmo del vecino ms cercano Ordenacin topolgica de un grafo Algoritmo de clculo de los componentes fuertemente conexos de un grafo Algoritmo de Dijkstra Algoritmo de Bellman-Ford Algoritmo de Prim Algoritmo de Ford-Fulkerson Algoritmo de Kruskal Algoritmo de Floyd-Warshall

Aplicaciones

Gracias a la teora de grafos se pueden resolver diversos problemas como por ejemplo la sntesis de circuitos secuenciales, contadores o sistemas de apertura. Se utiliza para diferentes reas por ejemplo, Dibujo computacional, en todas las reas de Ingeniera. Los grafos se utilizan tambin para modelar trayectos como el de una lnea de autobs a travs de las calles de una ciudad, en el que podemos obtener caminos ptimos para el trayecto aplicando diversos algoritmos como puede ser el algoritmo de Floyd. Para la administracin de proyectos, utilizamos tcnicas como PERT en las que se modelan los mismos utilizando grafos y optimizando los tiempos para concretar los mismos. La teora de grafos tambin ha servido de inspiracin para las ciencias sociales, en especial para desarrollar un concepto no metafrico de red social que sustituye los nodos por los actores sociales y verifica la posicin, centralidad e importancia de cada actor dentro de la red. Esta medida permite cuantificar y abstraer relaciones complejas, de manera que la estructura social puede representarse grficamente. Por ejemplo, una red social puede representar la estructura de poder dentro de una sociedad al identificar los vnculos (aristas), su direccin e intensidad y da idea de la manera en que el poder se transmite y a quines. Los grafos son importantes en el estudio de la biologa y hbitat. El vrtice representa un hbitat y las aristas (o "edges" en ingls) representa los senderos de los animales o las migracines. Con esta informacin, los cientficos pueden entender cmo esto puede cambiar o afectar a las especies en su hbitat. Grafo conexo En teora de grafos, un grafo G se dice conexo, si para cualquier par de vrtices a y b en G, existe al menos una trayectoria (una sucesin de vrtices adyacentes que no repita vrtices) de a a b. Definiciones Relacionadas Un grafo dirigido tal que para cualesquiera dos vrtices a y b existe un camino dirigido de ida y de regreso se dice grafo fuertemente conexo. Un conjunto de corte de vrtices U en un grafo G, es un conjunto de vrtices de G, tal que G-U no es conexo o trivial. Similarmente, un conjunto de corte de aristas F es un conjunto de aristas tal que G-F no es conexo. Solucin Computacional El problema computacional de determinar si un grafo es conexo, puede ser resuelto con algunos algoritmos como el MFMC (max-flow, min-cut). Algoritmo

Ejemplo de algoritmo iterativo implementado en C++ para determinar si un grafo es conexo utilizando Bsqueda_en_profundidad. bool Graph::is_connected() { if( _n <= 1 ) return true; vector<bool> visit(_n); vector<bool>::iterator iter; for(iter=visit.begin();iter!= visit.end();iter++) *iter=false; set<int> forvisit; set<int>::iterator actual; forvisit.insert(0); while( !forvisit.empty() ) { actual = (forvisit.begin()); if( visit[*actual] == false ) { for(int i=0;i<_n;i++) { if( _graph[*actual][i] == 1 && !visit[i]) forvisit.insert(i); } } visit[*actual]= true; forvisit.erase(actual); } bool result; for(iter=visit.begin();iter!= visit.end();iter++) result = result && *iter; return result; } Donde _n es la cantidad de vrtices y _graph denota la matrix de adyacencia. Ordenacin topolgica Una ordenacin topolgica de un grafo acclico G dirigido es una ordenacin lineal de todos los nodos de G que conserva la unin entre vrtices del grafo G original. La condicin que el grafo no contenga

ciclos es importante, ya que no se puede obtener ordenacin topolgica de grafos que contengan ciclos. Usualmente, para clarificar el concepto se suelen identificar los nodos con tareas a realizar en la que hay una precedencia a la hora de ejecutar dichas tareas. La ordenacin topolgica por tanto es una lista en orden lineal en que deben realizarse las tareas. Para poder encontrar la ordenacin topolgica del grafo G deberemos aplicar una modificacin del algoritmo de bsqueda en profundidad (DFS). Algoritmos Los algoritmos usuales para el ordenamiento topolgico tienen un tiempo de ejecucin de la cantidad de nodos ms la cantidad de aristas (O(|V|+|E|)). Uno de los algoritmos, primero descrito por Kahn (1962), trabaja eligiendo los vrtices del mismo orden como un eventual orden topolgico. Primero, busca la lista de los "nodos iniciales" que no tienen arcos entrantes y los inserta en un conjunto S; donde al menos uno de esos nodos existe si el grafo es acclico. Entonces: L Lista vaca que contendr luego los elementos ordenados. S Conjunto de todos los nodos sin aristas entrantes. MIENTRAS [S no es vaco]: n nodo extrado de S insertar n en L PARA CADA [nodo m con arista e de n a m]: e arista extrada del grafo SI [m no tiene ms aristas entrantes]: insertar m en S SI [el grafo tiene ms aristas]: error: el grafo tiene al menos un ciclo SINO: RETORNAR L Si respeta la definicin de GAD, sta es una solucin posible, listada en L (no es la nica solucin). De lo contrario el grafo contiene al menos un ciclo y por lo tanto un ordenamiento topolgico es imposible. Ha de tenerse en cuenta que, debido a la falta de unicidad del orden resultante, la estructura S puede ser simplemente un conjunto, una cola o una pila.

Dependiendo del orden que los nodos "n" son extrados del conjunto S, hay una diferente posible solucin. Una alternativa al algoritmo visto para ordenamiento topolgico est basado en DFS (del ingls bsqueda en profundidad). Para este algoritmo, las aristas estn en direccin contraria al algoritmo anterior (y en direccin contraria a lo que muestra el diagrama del ejemplo). Hay un arco desde x a y si la tarea x depende de la tarea y (en otras palabras, si la tarea y debe completarse antes que la tarea x empiece). El algoritmo se repite a travs de cada nodo del grafo, en un orden arbitrario, iniciando una bsqueda en profundidad que termina cuando llega a un nodo que ya ha sido visitado desde el comienzo del orden topolgico. La ordenacin topolgica no es nica. Depende en qu orden recorras los nodos del grafo en el bucle for de la funcin ORDENACIN_TOPOLGICA. La nomenclatura adicional utilizada es: lista = Estructura de datos lista enlazada ORDENACIN_TOPOLGICA(grafo G) for each vertice u V[G]do estado[u] = NO_VISITADO padre[u] = NULL tiempo =0 for each vertice u V[G]do if estado[u] = NO_VISITADO then TOPOLGICO-Visitar(u) TOPOLGICO-Visitar(nodo u) estado[u]=VISITADO tiempo = tiempo+1 distancia[u] = tiempo for each v Adyacencia[u] do if estado[v]=NO_VISITADO then padre[v]=u TOPOLGICO-Visitar(v) estado[u] = TERMINADO tiempo = tiempo+1 finalizacin[u] = tiempo insertar (lista, u) Al final de la ejecucin del algoritmo se devuelve la lista enlazada de nodos, que corresponde con la ordenacin topolgica del grafo . Ejemplos

En rojo se muestran los siguientes tiempos: distancia[u] / finalizacin[u]

1. Ejecutamos el algoritmo ORDENACIN_TOPOLGICA (grafo G) sobre el siguiente grafo.

2. El algoritmo nos devuelve una lista enlazada con los nodos del grafo en orden decreciente en tiempo de finalizacin.

Grafo ordenado topolgicamente. En l se pueden ver claramente las precedencias de las tareas:

Ponerse la camisa antes que el cinturn y el jersey Ponerse el pantaln antes que los zapatos y el cinturn Ponerse los calcetines antes que los zapatos

La aplicacin cannica del orden topolgico es en programacin, una secuencia de tareas; los algoritmos de ordenamiento topolgico fueron estudiados por primera vez a los comienzos de los aos 60 en el contexto de la tcnica "PERT" (Tcnica de Revisin y Evaluacin de Programas del ingls) de programacin en gestin de proyectos ((Jarnagin, ,1960)). Las tareas estn representados por vrtices, y hay un arco (o arista) desde x a y si la tarea x debe completarse antes que la tarea y comience (por ejemplo, cuando se lava la ropa, la lavadora debe terminar antes de ponerla a secar). Entonces, un orden topolgico brinda un orden para ejecutar las tareas.

El grfico muestra que hay muchos tipos de ordenamiento posibles:


7, 5, 3, 11, 8, 2, 9, 10 (visto de izquierda a derecha, de arriba a abajo) 3, 5, 7, 8, 11, 2, 9, 10 (por nmeros menores primero) 3, 7, 8, 5, 11, 10, 2, 9 5, 7, 3, 8, 11, 10, 9, 2 (por menor cantidad de aristas primero) 7, 5, 11, 3, 10, 8, 9, 2 (por nmeros mayores primero) 7, 5, 11, 2, 3, 8, 9, 10

Componente fuertemente conexo

Un grafo dirigido, y sus componentes fuertemente conexos. En la Teora de los grafos, un grafo dirigido es llamado fuertemente conexo si para cada par de vrtices u y v existe un camino de u hacia v y un camino de v hacia u. Los componentes fuertemente conexos (CFC) de un grafo dirigido son sus subgrafos mximos fuertemente conexos. Estos subgrafos forman una particin del grafo. Un subgrafo fuertemente conexo es mximo si contiene todos los vrtices del grafo o si al agregarle un vrtice cualquiera deja de ser fuertemente conexo. El clculo de los componentes fuertemente conexos de un grafo es uno de los problemas fundamentales de la Teora de los grafos. El primer algoritmo que trabaja en tiempo lineal para resolver este problema fue propuesto por Robert Tarjan1 en 1970 a base de una bsqueda en profundidad (depth-first search). Otros algoritmos aparecen en los principales textos sobre algortmica.2 3 La complejidad de este algoritmo es O(V+E). Algoritmo Sea un grafo dirigido: 1. Aplicar bsqueda en profundidad sobre G 2. Calcular el grafo traspuesto.

3. Aplicar bsqueda en profundidad sobre Gt (el grafo traspuesto) iniciando la bsqueda en los nodos de mayor a menor tiempo de finalizacin obtenidos en la primera ejecucin de bsqueda en profundidad (paso 1) 4. El resultado ser un bosque de rboles. Cada rbol es una componente fuertemente conexa. Las dos bsquedas en profundidad y la construccin del grafo reverso consumen tiempo lineal, de manera que el tiempo total es tambin lineal. En 2002, se public4 una prueba de correccin de este algortmo. Bsqueda en anchura En Ciencias de la Computacin, Bsqueda en anchura (en ingls BFS - Breadth First Search) es un algoritmo para recorrer o buscar elementos en un grafo (usado frecuentemente sobre rboles). Intuitivamente, se comienza en la raz (eligiendo algn nodo como elemento raz en el caso de un grafo) y se exploran todos los vecinos de este nodo. A continuacin para cada uno de los vecinos se exploran sus respectivos vecinos adyacentes, y as hasta que se recorra todo el rbol. Formalmente, BFS es un algoritmo de bsqueda sin informacin, que expande y examina todos los nodos de un rbol sistemticamente para buscar una solucin. El algoritmo no usa ninguna estrategia heurstica. Si las aristas tienen pesos negativos aplicaremos el algoritmo de Bellman-Ford en alguna de sus dos versiones. Procedimiento

Dado un vrtice fuente s, Breadth-first search sistemticamente explora los vrtices de G para descubrir todos los vrtices alcanzables desde s. Calcula la distancia (menor nmero de vrtices) desde s a todos los vrtices alcanzables. Despus produce un rbol BF con raz en s y que contiene a todos los vrtices alcanzables. El camino desde s a cada vrtice en este recorrido contiene el mnimo nmero de vrtices. Es el camino ms corto medido en nmero de vrtices. Su nombre se debe a que expande uniformemente la frontera entre lo descubierto y lo no descubierto. Llega a los nodos de distancia k, slo tras haber llegado a todos los nodos a distancia k-1.

Pseudocdigo

La nomenclatura adicional utilizada es: Q = Estructura de datos cola

BFS(grafo G, nodo_fuente s) { // recorremos todos los vrtices del grafo inicializndolos a NO_VISITADO, // distancia INFINITA y padre de cada nodo NULL for u V[G] do { estado[u] = NO_VISITADO; distancia[u] = INFINITO; /* distancia infinita si el nodo no es alcanzable */ padre[u] = NULL; } estado[s] = VISITADO; distancia[s] = 0; Encolar(Q, s); while !vacia(Q) do { // extraemos el nodo u de la cola Q y exploramos todos sus nodos adyacentes u = extraer(Q); for v adyacencia[u] do { if estado[v] == NO_VISITADO then { estado[v] = VISITADO; distancia[v] = distancia[u] + 1; padre[v] = u; Encolar(Q, v); } } } } *Falta recorrer vertices no adyacentes directa o indirectamente al vertice origen "s", pues cola queda vacia sin los adyacentes restantes.

El tiempo de ejecucin es O(|V|+|E|). Ntese que cada nodo es puesto a la cola una vez y su lista de adyacencia es recorrida una vez tambin.

Anexo:Ejemplo de Algoritmo de Bellman - Ford

Grafo inicial

Camino mnimo final de todos los nodos al primero En este artculo se mostrar un ejemplo del Algoritmo de Bellman-Ford. Para ello se mostrar la siguiente tabla y a partir de esta se explicar el procedimiento para hallar el camino mnimo de todos los vrtices a un nico vrtice destino. Ejemplo Grafo inicial y Tabla de relaciones En este ejemplo partimos de este grafo, cuyas relaciones estn expuestas a su derecha:

Tabla de resolucin final En esta tabla se muestran las soluciones parciales que se han ido obteniendo a travs de la realizacin del algoritmo.

Explicacin del algoritmo En la tabla anterior donde queda desarrollado el algoritmo paso por paso, podemos apreciar que la resolucin del algoritmo viene dada por aplicar las frmulas que vienen escritas en el paso n, a cada paso. El objetivo del algoritmo es encontrar el camino mnimo desde todos los nodos al vrtice 1. En las frmulas donde viene D, es la distancia mnima desde el nodo que aparece en el subndice al vrtice destino, en este caso, el vrtice 1.

En el paso 0, inicializamos todas las distancias mnimas a INFINITO. En el paso 1, actualizamos el paso anterior, aplicando las frmulas. En este caso ponemos la distancia de los nodos que tienen accesos directos al vrtice 1 y se la sumamos a la distancia mnima acumulada que hay hasta el vrtice oportuno. Aqu esta distancia acumulada sera 0 para 1, debido a que sera la distancia a l mismo, e infinito para el resto porque no han sido analizados todava. En el paso 2, al saber ya una distancia mnima acumulada desde los nodos 2 y 3 hasta 1, podemos actualizar las distancias mnimas de los nodos 4 y 5. En los pasos sucesivos, se van actualizando las distancias mnimas acumuladas (D) de los distintos vrtices hasta 1, y se van utilizando en los pasos siguientes para optimizar el camino mnimo. El final del algoritmo se da cuando no hay ningn cambio de un paso a otro, es decir, cuando ya no se puede encontrar un camino ms corto.

Algoritmo de Bellman-Ford El algoritmo de Bellman-Ford (algoritmo de Bell-End-Ford), genera el camino ms corto en un Grafo dirigido ponderado (en el que el peso de alguna de las aristas puede ser negativo). El algoritmo de Dijkstra resuelve este mismo problema en un tiempo menor, pero requiere que los pesos de las aristas no sean negativos. Por lo que el Algoritmo Bellman-Ford normalmente se utiliza cuando hay aristas con peso negativo. Este algoritmo fue desarrollado por Richard Bellman, Samuel End y Lester Ford. Segn Robert Sedgewick, Los pesos negativos no son simplemente una curiosidad matemtica; *+ surgen de una forma natural en la reduccin a problemas de caminos ms cortos, y son un ejemplo de una reduccin del problema del camino hamiltoniano que es NP-completo hasta el problema de caminos ms cortos con pesos generales. Si un grafo contiene un ciclo de coste total negativo entonces este grafo no tiene solucin. El algoritmo es capaz de detectar este caso. Si el grafo contiene un ciclo de coste negativo, el algoritmo lo detectar, pero no encontrar el camino ms corto que no repite ningn vrtice. La complejidad de este problema es al menos la del problema del camino ms largo de complejidad NP-Completo.

Algoritmo El Algoritmo de Bellman-Ford es, en su estructura bsica, muy parecido al algoritmo de Dijkstra, pero en vez de seleccionar vorazmente el nodo de peso mnimo aun sin procesar para relajarlo, simplemente relaja todas las aristas, y lo hace |V|-1 veces, siendo |V| el nmero de vrtices en el grafo. Las repeticiones permiten a las distancias mnimas recorrer el rbol, ya que en la ausencia de ciclos negativos, el camino ms corto solo visita cada vrtice una vez. A diferencia de la solucin voraz, la cual depende de la suposicin de que los pesos sean positivos, esta solucin se aproxima ms al caso general. Existen dos versiones:

Versin no optimizada para grafos con ciclos negativos, cuyo coste de tiempo es O(VE) Versin optimizada para grafos con aristas de peso negativo, pero en el grafo no existen ciclos de coste negativo, cuyo coste de tiempo, es tambin O(VE).

BellmanFord(Grafo G, nodo_origen s) // inicializamos el grafo. Ponemos distancias a INFINITO menos el nodo origen que // tiene distancia 0 for v V[G] do distancia[v]=INFINITO predecesor[v]=NIL distancia[s]=0 // relajamos cada arista del grafo tantas veces como nmero de nodos -1 haya en el grafo for i=1 to |V[G]-1| do for (u, v) E[G] do if distancia[v]>distancia[u] + peso(u, v) then distancia[v] = distancia[u] + peso (u, v) predecesor[v] = u // comprobamos si hay ciclos negativo for (u, v) E[G] do if distancia[v] > distancia[u] + peso(u, v) then print ("Hay ciclo negativo") return FALSE return TRUE BellmanFord_Optimizado(Grafo G, nodo_origen s) // inicializamos el grafo. Ponemos distancias a INFINITO menos el nodo origen que // tiene distancia 0. Para ello lo hacemos recorrindonos todos los vrtices del grafo for v V[G] do distancia[v]=INFINITO padre[v]=NIL distancia[s]=0

encolar(s, Q) en_cola[s]=TRUE mientras Q!=0 then u = extraer(Q) en_cola[u]=FALSE // relajamos las aristas for v ady[u] do if distancia[v]>distancia[u] + peso(u, v) then distancia[v] = distancia[u] + peso (u, v) padre[v] = u if en_cola[v]==FALSE then encolar(v, Q) en_cola[v]=TRUE Demostracin de la correccin del algoritmo La correccin del algoritmo se puede demostrar por induccin. La demostracin es la siguiente: Lema. Tras i repeticiones del bucle for:

Si distancia(u) no es infinita, entonces es igual a la longitud de algn camino de s hasta u. Si hay un camino desde s hasta u con al menos i aristas, entonces distancia(u) es a lo sumo la longitud del camino ms corto desde s hasta u con i aristas como mximo.

Demostracin. Para el caso base de la induccin, consideramos i=0 y justo antes el bucle for es ejecutado por primera vez. Luego, para el vrtice origen distancia(origen) = 0, lo que es cierto. Para cualquier otro vrtice u distancia(u) = INFINITO, lo cual es tambin correcto porque no hay camino desde origen hasta u con 0 aristas.

Para el caso inductivo, primero demostramos la primera parte. Considerando un momento en el que la distancia hasta el vrtice es actualizada por distancia(u)= distancia(u)+peso(uv). Por la hiptesis de induccin, distancia(u) es la longitud de algn camino desde origen hasta u. Entonces distancia(u) + peso(uv) es la longitud del camino desde la origen hasta v que sigue el camino desde origen hasta u y luego va a v. Para la segunda parte, tomamos el camino ms corto desde origen hasta u con al menos i aristas. Dejamos a v ser el ltimo vrtice antes de u en su camino. Luego, la parte del camino desde origen hasta v es el camino ms corto desde origen hasta v con al menos i-1 aristas. Por la hiptesis de induccin, distancia(v) despus de i-1 iteraciones es a lo sumo la longitud de su camino. Entonces, peso(uv) + distancia(v) es a lo sumo la longitud del camino desde s hasta u. En el primer ciclo, distancia(u) es comparada con peso(uv) + distancia(v), y es igual a l si peso(uv) + distancia(v)era menor. Entonces, tras i iteraciones, distancia(u) es a lo sumo la longitud del camino ms corto desde origen hasta u que usa al menos i aristas.

Si no hay ciclos de peso negativo, entonces cada camino ms corto visita cada vrtice al menos una vez, as que al paso 3 no se le pueden aadir mejoras. Por el contrario, supongamos que no se puede hacer ningn cambio. Entonces para cualquier vrtice v[0],..,v[k-1], Distancia(v[i]) <= Distancia(v[i-1 (mod k)]) + peso(v[i-1 (mod k)]v[i]) Simplificando, distancia(v[i]) y distancia(v[i-1 (mod k)]) se cancelan, dejando:

Es decir, cada ciclo tiene pesos no negativos Aplicaciones de encaminamiento Una variante distribuida del Algoritmo del Bellman-Ford se usa en protocolos de encaminamiento basados en vector de distancias, por ejemplo el Protocolo de encaminamiento de informacin (RIP). El algoritmo es distribuido porque envuelve una serie de nodos (routers) dentro de un Sistema autnomo(AS), un conjunto de redes y dispositivos router IP administrados tpicamente por un Proveedor de Servicio de Internet (ISP). Se compone de los siguientes pasos: 1. Cada nodo calcula la distancia entre l mismo y todos los dems dentro de un AS y almacena esta informacin en una tabla. 2. Cada nodo enva su tabla a todos los nodos vecinos. 3. Cuando un nodo recibe las tablas de distancias de sus vecinos, ste calcula la ruta ms corta a los dems nodos y actualiza su tabla para reflejar los cambios. Las desventajas principales del algoritmo de Bellman-Ford en este ajuste son:

No escala bien Los cambios en la topologa de red no se reflejan rpidamente ya que las actualizaciones se distribuyen nodo por nodo. Contando hasta el infinito(si un fallo de enlace o nodo hace que un nodo sea inalcanzable desde un conjunto de otros nodos, stos pueden estar siempre aumentando gradualmente sus clculos de distancia a l, y mientras tanto puede haber bucles de enrutamiento)

Mejoras En 1970 Yen describi una mejora del algoritmo Bellman-Ford para un grafo sin ciclos con peso negativo. Esta mejora primero asigna un orden arbitrario lineal a todos los vrtices y luego divide el conjunto de todas las aristas en uno o dos subconjuntos. El primer subconjunto, E f, contiene todas las aristas (vi,vj) tales que i < j; mientras que el segundo, Eb, contiene aristas (vi,vj) tales que i > j. Cada vrtice se visita en orden v1,v2,,v|v|, relajando cada arista saliente de ese vrtice en Ef. Cada vrtice es, despus, visitado en orden v|v|,v|v|,,v1, relajando cada arista saliente de ese vrtice en Eb. La mejora de Yen reduce a la mitad, de manera efectiva, el nmero de pases requeridos para la solucin del camino ms corto desde una nica fuente.

Bsqueda en profundidad Una Bsqueda en profundidad (en ingls DFS o Depth First Search) es un algoritmo que permite recorrer todos los nodos de un grafo o rbol (teora de grafos) de manera ordenada, pero no uniforme. Su funcionamiento consiste en ir expandiendo todos y cada uno de los nodos que va localizando, de forma recurrente, en un camino concreto. Cuando ya no quedan ms nodos que visitar en dicho camino, regresa (Backtracking), de modo que repite el mismo proceso con cada uno de los hermanos del nodo ya procesado. Anlogamente existe el algoritmo de bsqueda en anchura (BFS o Breadth First Search). Pseudocdigo

Pseudocdigo para grafos

DFS(grafo G) PARA CADA vertice u V[G] HACER estado[u+ NO_VISITADO padre[u+ NULO tiempo 0 PARA CADA vertice u V[G] HACER SI estado[u] = NO_VISITADO ENTONCES DFS_Visitar(u) DFS-Visitar(nodo u) estado[u+ VISITADO tiempo tiempo + 1 d*u+ tiempo PARA CADA v Vecinos[u] HACER SI estado[v] = NO_VISITADO ENTONCES padre[v+ u DFS_Visitar(v) estado[u+ TERMINADO tiempo tiempo + 1 f[u] tiempo Arcos DF Si en tiempo de descubrimiento de u tenemos el arco (u,v): i. Si el estado de v es NO_VISITADO, entonces (u,v) DF, Algoritmo de bsqueda A*

Ejemplo de aplicacin del algoritmo A*. El algoritmo de bsqueda A* (A Asterisco) se clasifica dentro de los algoritmos de bsqueda en grafos. Presentado por primera vez en 1968 por Peter E. Hart, Nils J. Nilsson y Bertram Raphael, el algoritmo encuentra, siempre y cuando se cumplan unas determinadas condiciones, el camino de menor coste entre un nodo origen y uno objetivo. Motivacin y Descripcin El problema de algunos algoritmos de bsqueda en grafos informados, como puede ser el algoritmo voraz, es que se guan en exclusiva por la funcin heurstica, la cual puede no indicar el camino de coste ms bajo, o por el coste real de desplazarse de un nodo a otro (como los algoritmos de escalada), pudindose dar el caso de que sea necesario realizar un movimiento de coste mayor para alcanzar la solucin. Es por ello bastante intuitivo el hecho de que un buen algoritmo de bsqueda informada debera tener en cuenta ambos factores, el valor heurstico de los nodos y el coste real del recorrido. As, el algoritmo A* utiliza una funcin de evaluacin f(n) = g(n) + h'(n), donde h'(n) representa el valor heurstico del nodo a evaluar desde el actual, n, hasta el final, y g(n), el coste real del camino recorrido para llegar a dicho nodo, n. A* mantiene dos estructuras de datos auxiliares, que podemos denominar abiertos, implementado como una cola de prioridad (ordenada por el valor f(n) de cada nodo), y cerrados, donde se guarda la informacin de los nodos que ya han sido visitados. En cada paso del algoritmo, se expande el nodo que est primero en abiertos, y en caso de que no sea un nodo objetivo, calcula la f(n) de todos sus hijos, los inserta en abiertos, y pasa el nodo evaluado a cerrados. El algoritmo es una combinacin entre bsquedas del tipo primero en anchura con primero en profundidad: mientras que h'(n) tiende a primero en profundidad, g(n) tiende a primero en anchura. De este modo, se cambia de camino de bsqueda cada vez que existen nodos ms prometedores. Propiedades Como todo algoritmo de bsqueda en anchura, A* es un algoritmo completo: en caso de existir una solucin, siempre dar con ella.

Si para todo nodo n del grafo se cumple g(n) = 0, nos encontramos ante una bsqueda voraz. Si para todo nodo n del grafo se cumple h(n) = 0, A* pasa a ser una bsqueda de coste uniforme no informada. Para garantizar la optimalidad del algoritmo, la funcin h(n) debe ser admisible, esto es, que no sobrestime el coste real de alcanzar el nodo objetivo. De no cumplirse dicha condicin, el algoritmo pasa a denominarse simplemente A, y a pesar de seguir siendo completo, no se asegura que el resultado obtenido sea el camino de coste mnimo. Asimismo, si garantizamos que h(n) es consistente (o montona), es decir, que para cualquier nodo n y cualquiera de sus sucesores, el coste estimado de alcanzar el objetivo desde n no es mayor que el de alcanzar el sucesor ms el coste de alcanzar el objetivo desde el sucesor. Complejidad computacional La complejidad computacional del algoritmo est ntimamente relacionada con la calidad de la heurstica que se utilice en el problema. En el caso peor, con una heurstica de psima calidad, la complejidad ser exponencial, mientras que en el caso mejor, con una buena h'(n), el algoritmo se ejecutar en tiempo lineal. Para que esto ltimo suceda, se debe cumplir que

donde h* es una heurstica ptima para el problema, como por ejemplo, el coste real de alcanzar el objetivo. Complejidad en memoria El espacio requerido por A* para ser ejecutado es su mayor problema. Dado que tiene que almacenar todos los posibles siguientes nodos de cada estado, la cantidad de memoria que requerir ser exponencial con respecto al tamao del problema. Para solucionar este problema, se han propuesto diversas variaciones de este algoritmo, como pueden ser RTA*, IDA* o SMA*. Implementacin en pseudocdigo Tratar punto .:= . // coste del camino hasta . caso . = . perteneciente a () si g(.) < g(.) entonces // (-----) // nos quedamos con el camino de menor coste .:= MEJORNODO actualizar g(.) y f'(.)

propagar g a . de . eliminar . aadir . a ._MEJORNODO caso . = . perteneciente a )-----( si g(.) < g(.) entonces // nos quedamos con el camino de menor coste .:= MEJORNODO actualizar g(.) y f'(.) eliminar . aadir . a ._MEJORNODO caso . no estaba en ).( ni (.) aadir . a ).( aadir . a ._MEJORNODO f'(.) := g(.) + h'(.) Observaciones Como se mencion anteriormente h'(x) es un estimador de h(x) que informa la distancia al nodo objetivo, entonces Si h'(x) hace un estimacin perfecta de h(x), A* converge inmediatamente al objetivo. Si h'(x) = 0, la funcin g(x) controla la bsqueda. Si h'(x) = 0 y g(x) =0 la bsqueda ser aleatoria. Si h'(x) = 0 y g(x) =1 o constante la bsqueda ser Primero en Anchura. Si h'(x) nunca sobrestima a h(x) (o subestima), se garantiza encontrar el camino optimo, pero se desperdicia esfuerzo explorando otras rutas que parecieron buenas. Si h'(x) sobrestima a h(x), no puede garantizarse la consecucin del camino del menor coste Algoritmo de Prim El algoritmo de Prim es un algoritmo perteneciente a la teora de los grafos para encontrar un rbol recubridor mnimo en un grafo conexo, no dirigido y cuyas aristas estn etiquetadas. En otras palabras, el algoritmo encuentra un subconjunto de aristas que forman un rbol con todos los vrtices, donde el peso total de todas las aristas en el rbol es el mnimo posible. Si el grafo no es conexo, entonces el algoritmo encontrar el rbol recubridor mnimo para uno de los componentes conexos que forman dicho grafo no conexo.

El algoritmo fue diseado en 1930 por el matemtico Vojtech Jarnik y luego de manera independiente por el cientfico computacional Robert C. Prim en 1957 y redescubierto por Dijkstra en 1959. Por esta razn, el algoritmo es tambin conocido como algoritmo DJP o algoritmo de Jarnik. Descripcin conceptual El algoritmo incrementa continuamente el tamao de un rbol, comenzando por un vrtice inicial al que se le van agregando sucesivamente vrtices cuya distancia a los anteriores es mnima. Esto significa que en cada paso, las aristas a considerar son aquellas que inciden en vrtices que ya pertenecen al rbol. El rbol recubridor mnimo est completamente construido cuando no quedan ms vrtices por agregar. Pseudocdigo del algoritmo

Estructura de datos auxiliar: Q = Estructura de datos Cola de prioridad (se puede implementar con un heap)

JARNIK (Grafo G, nodo_fuente s) // Inicializamos todos los nodos del grafo. La distancia la ponemos a infinito y el padre de cada nodo a NULL // Encolamos, en una cola de prioridad donde la prioridad es la distancia, todas las parejas <nodo,distancia> del grafo por cada u en V[G] hacer distancia[u] = INFINITO padre[u] = NULL Aadir(cola,<u,distancia[u]>) distancia[s]=0 mientras cola != 0 do // OJO: Se entiende por mayor prioridad aquel nodo cuya distancia[u] es menor. u = extraer_minimo(cola) //devuelve el minimo y lo elimina de la cola. por cada v adyacente a 'u' hacer si ((v cola) && (distancia[v] > peso(u, v)) entonces padre[v] = u distancia[v] = peso(u, v) Actualizar(cola,<v,distancia[v]>) Cdigo en JAVA public class Algorithms { public static Graph PrimsAlgorithm (Graph g, int s) {

int n = g.getNumberOfVertices (); Entry[] table = new Entry [n]; for (int v = 0; v < n; ++v) table [v] = new Entry (); table [s].distance = 0; PriorityQueue queue = new BinaryHeap (g.getNumberOfEdges()); queue.enqueue ( new Association (new Int (0), g.getVertex (s))); while (!queue.isEmpty ()) { Association assoc = (Association) queue.dequeueMin(); Vertex v0 = (Vertex) assoc.getValue (); int n0 = v0.getNumber (); if (!table [n0].known) { table [n0].known = true; Enumeration p = v0.getEmanatingEdges (); while (p.hasMoreElements ()) { Edge edge = (Edge) p.nextElement (); Vertex v1 = edge.getMate (v0); int n1 = v1.getNumber (); Int wt = (Int) edge.getWeight (); int d = wt.intValue (); if (!table[n1].known && table[n1].distance>d) { table [n1].distance = d; table [n1].predecessor = n0; queue.enqueue ( new Association (new Int (d), v1)); } } } } Graph result = new GraphAsLists (n); for (int v = 0; v < n; ++v) result.addVertex (v); for (int v = 0; v < n; ++v) if (v != s) result.addEdge (v, table [v].predecessor); return result; } }

Demostracin Sea G un grafo conexo y ponderado. En toda iteracin del algoritmo de Prim, se debe encontrar una arista que conecte un nodo del subgrafo a otro nodo fuera del subgrafo. Ya que G es conexo, siempre habr un camino para todo nodo. La salida Y del algoritmo de Prim es un rbol porque las aristas y los nodos agregados a Y estn conectados. Sea Y el rbol recubridor mnimo de G. Si es el rbol recubridor mnimo.

Si no, sea e la primera arista agregada durante la construccin de Y, que no est en Y1 y sea V el conjunto de nodos conectados por las aristas agregadas antes que e. Entonces un extremo de e est en V y el otro no. Ya que Y1 es el rbol recubridor mnimo de G hay un camino en Y1 que une los dos extremos. Mientras que uno se mueve por el camino, se debe encontrar una arista f uniendo un nodo en V a uno que no est en V. En la iteracin que e se agrega a Y, f tambin se podra haber agregado y se hubiese agregado en vez de e si su peso fuera menor que el de e. Ya que f no se agreg se concluye:

Sea Y2 el grafo obtenido al remover f y agregando . Es fcil mostrar que Y2 conexo tiene la misma cantidad de aristas que Y1, y el peso total de sus aristas no es mayor que el de Y1, entonces tambin es un rbol recubridor mnimo de G y contiene a e y todas las aristas agregadas anteriormente durante la construccin de V. Si se repiten los pasos mencionados anteriormente, eventualmente se obtendr el rbol recubridor mnimo de G que es igual a Y. Esto demuestra que Y es el rbol recubridor mnimo de G. Ejemplo de ejecucin del algoritmo Image Descripcin No En el visto grafo En el rbol

Este es el grafo ponderado de partida. No es un rbol ya que requiere que no haya ciclos y en este grafo los hay. Los nmeros cerca de las aristas indican el peso. Ninguna de las aristas est marcada, y el vrtice D ha sido elegido arbitrariamente como el punto de partida.

C, G

A, B, E, F

El segundo vrtice es el ms cercano a D: A est a 5 de distancia, B a 9, E a 15 y F a 6. De estos, 5 es el valor ms pequeo, as que marcamos la arista DA.

C, G

B, E, F

A, D

El prximo vrtice a elegir es el ms cercano a D o A. B est a 9 de distancia de D y a 7 de A, E est a 15, y F est a 6. 6 es el valor ms C pequeo, as que marcamos el vrtice F y a la arista DF.

B, E, G

A, D, F

El algoritmo continua. El vrtice B, que est a una distancia de 7 de A, es el siguiente marcado. En este punto la arista DB es marcada en rojo porque sus dos extremos ya estn en el rbol y por lo tanto no podr ser utilizado.

null

C, E, G

A, D, F, B

Aqu hay que elegir entre C, E y G. C est a 8 de distancia de B, E est a 7 de distancia de B, y G est a 11 de distancia de F. E est ms cerca, entonces marcamos el vrtice E y la null arista EB. Otras dos aristas fueron marcadas en rojo porque ambos vrtices que unen fueron agregados al rbol.

C, G

A, D, F, B, E

Slo quedan disponibles C y G. C est a 5 de distancia de E, y G a 9 de distancia de E. Se elige C, y se marca con el arco EC. El arco BC tambin se marca con rojo.

null

A, D, F, B, E, C

G es el nico vrtice pendiente, y est ms cerca de E que de F, as que se agrega EG al rbol. Todos los vrtices estn ya marcados, el rbol de expansin mnimo se muestra en verde. En este caso con un peso de 39.

null

null

A, D, F, B, E, C, G

rbol recubridor mnimo

Un ejemplo de rbol recubridor mnimo. Cada punto representa un vrtice, cada arista est etiquetada con su peso, que en este caso equivale a su longitud. Dado un grafo conexo, un rbol recubridor mnimo de ese grafo es un subgrafo que tiene que ser un rbol y contener todos los vrtices del grafo inicial. Cada arista tiene asignado un peso proporcional entre ellos, que es un nmero representativo de algn objeto, distancia, etc.. , y se usa para asignar un peso total al rbol recubridor mnimo computando la suma de todos los pesos de las aristas del rbol en cuestin. Un rbol recubridor mnimo o un rbol expandido mnimo es un rbol recubridor que pesa menos o igual que otros rboles recubridores. Todo grafo tiene un bsque recubridor mnimo.

Un ejemplo sera una compaa de cable trazando cable a una nueva vecindad. Si est limitada a trazar el cable por ciertos caminos, entonces se har un grafo que represente los puntos conectados por esos caminos. Algunos de estos caminos podrn ser ms caros que otros, por ser ms largos. Estos caminos seran representados por las aristas con mayores pesos. Un rbol recubridor para este grafo sera un subconjunto de estos caminos que no tenga ciclos pero que mantenga conectadas todas las casas. Puede haber ms de un rbol recubridor posible. El rbol recubridor mnimo ser el de menos coste. En el caso de un empate, porque podra haber ms de un rbol recubridor mnimo; en particular, si todos los pesos son iguales, todo rbol recubridor ser mnimo. De todas formas, si cada arista tiene un peso distinto existir slo un rbol recubridor mnimo. La demostracin de esto es trivial y se puede hacer por induccin. Esto ocurre en muchas situaciones de la realidad, como con la compaa de cable en el ejemplo anterior, donde es extrao que dos caminos tengan exactamente el mismo coste. Esto tambin se generaliza para los bsques recubridores. Si los pesos son positivos, el rbol recubridor mnimo es el subgrafo de menor costo posible conectando todos los vrtices, ya que los subgrafos que contienen ciclos necesariamente tienen ms peso total. Algoritmo de Ford-Fulkerson El algoritmo de Ford-Fulkerson propone buscar caminos en los que se pueda aumentar el flujo, hasta que se alcance el flujo mximo. Es aplicable a los Flujos maximales. La idea es encontrar una ruta de penetracin con un flujo positivo neto que una los nodos origen y destino. Su nombre viene dado por sus creadores, L. R. Ford, Jr. y D. R. Fulkerson. Introduccin Sea (V,A,w) con V vrtices, A aristas y w peso de las aristas, una red con una nica fuente s y un nico sumidero t; w() es la capacidad de perteneciente a la arista A. Un flujo f es viable si f() <= w() para todo perteneciente a la arista A. Se trata de hallar un flujo viable con el valor mximo posible.

En un red con fuente s y sumidero t nico el valor mximo que puede tomar un flujo variable es igual a la capacidad mnima que puede tomar un corte. Pseudocdigo Ford-Fulkerson(G,s,t) { for (cada arco (u,v) de E) { f[u,v]= 0; f[v,u]= 0; } while (exista un camino p desde s a t en la red residual Gf) { cf(p) = min{cf(u,v): (u,v) est sobre p}; for (cada arco (u,v) en p) { f[u,v]= f[u,v] + cf(p); f[v,u]= - f[u,v]; } } } Algoritmo de Kruskal El algoritmo de Kruskal es un algoritmo de la teora de grafos para encontrar un rbol recubridor mnimo en un grafo conexo y ponderado. Es decir, busca un subconjunto de aristas que, formando un rbol, incluyen todos los vrtices y donde el valor total de todas las aristas del rbol es el mnimo. Si el grafo no es conexo, entonces busca un bosque expandido mnimo (un rbol expandido mnimo para cada componente conexa). El algoritmo de Kruskal es un ejemplo de algoritmo voraz.

Un ejemplo de rbol expandido mnimo. Cada punto representa un vrtice, el cual puede ser un rbol por s mismo. Se usa el Algoritmo para buscar las distancias ms cortas (rbol expandido) que conectan todos los puntos o vrtices.

Funciona de la siguiente manera:


se crea un bosque B (un conjunto de rboles), donde cada vrtice del grafo es un rbol separado se crea un conjunto C que contenga a todas las aristas del grafo mientras C es no vaco o eliminar una arista de peso mnimo de C o si esa arista conecta dos rboles diferentes se aade al bosque, combinando los dos rboles en un solo rbol o en caso contrario, se desecha la arista

Al acabar el algoritmo, el bosque tiene un solo componente, el cual forma un rbol de expansin mnimo del grafo. Este algoritmo fue publicado por primera vez en Proceedings of the American Mathematical Society, pp. 4850 en 1956, y fue escrito por Joseph Kruskal. Pseudocdigo 1 function Kruskal(G) 2 for each vertex v in G do 3 Define an elementary cluster C(v) ,v}. 4 Initialize a priority queue Q to contain all edges in G, using the weights as keys. 5 Define a tree T //T will ultimately contain the edges of the MST 6 // n es el nmero total de vrtices 7 while T has fewer than n-1 edges do 8 // edge u, v is the minimum weighted route from/to v 9 (u,v) Q.removeMin() 10 // previene ciclos en T. suma u, v solo si T no contiene una arista que una u y v. 11 // Ntese que el cluster contiene ms de un vrtice si una arista une un par de 12 // vrtices que han sido aadidos al rbol. 13 Let C(v) be the cluster containing v, and let C(u) be the cluster containing u. 14 if C(v) C(u) then 15 Add edge (v,u) to T. 16 Merge C(v) and C(u) into one cluster, that is, union C(v) and C(u). 17 return tree T Complejidad del algoritmo m el nmero de aristas del grafo y n el nmero de vrtices, el algoritmo de Kruskal muestra una complejidad O(m log m) o, equivalentemente, O(m log n), cuando se ejecuta sobre estructuras de datos simples. Los tiempos de ejecucin son equivalentes porque:

m es a lo sumo n2 y log n2 = 2logn es O(log n).

ignorando los vrtices aislados, los cuales forman su propia componente del rbol de expansin mnimo, n 2m, as que log n es O(log m).

Se puede conseguir esta complejidad de la siguiente manera: primero se ordenan las aristas por su peso usando una ordenacin por comparacin (comparison sort) con una complejidad del orden de O(m log m); esto permite que el paso "eliminar una arista de peso mnimo 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 vrtices estn en qu componentes. Es necesario hacer orden de O( m) operaciones ya que por cada arista hay dos operaciones de bsqueda y posiblemente una unin 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 condicin de que las aristas estn 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 ms complejas para ejecutarse en tiempos del orden de O(m (n)), donde es la inversa (tiene un crecimiento extremadamente lento) de la funcin de Ackermann. Demostracin de la correccin 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 aade una arista, sta debe conectar vrtices de dos rboles diferentes y no vrtices dentro de un subrbol. Y no puede ser disconexa ya que la primera arista que une dos componentes de Y debera haber sido aadida por el algoritmo. Por tanto, Y es un rbol expandido de P. Sea Y1 el rbol expandido de peso mnimo de P, el cual tiene el mayor nmero de aristas en comn con Y. Si Y1=Y entonces Y es un rbol de expansin mnimo. 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 tambin conecta C1 y C2. Entonces Y2=Y1+e-f es tambin 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 mnimo, los pesos de esas dos aristas deben ser de hecho iguales. Por tanto, Y2 es un rbol expandido mnimo con ms aristas en comn con Y que las que tiene Y1, contradiciendo las hiptesis que se haban establecido antes para Y1. Esto prueba que Y debe ser un rbol expandido de peso mnimo. Otros algoritmos para este problema son el algoritmo de Prim y el algoritmo de Boruvka. Ejemplo

Este es el grafo original. Los nmeros de las aristas indican su peso. Ninguna de las aristas est resaltada.

AD y CE son las aristas ms cortas, con peso 5, y AD se ha elegido arbitrariamente, por tanto se resalta.

Sin embargo, ahora es CE la arista ms pequea que no forma ciclos, con peso 5, por lo que se resalta como segunda arista.

La siguiente arista, DF con peso 6, ha sido resaltada utilizando el mismo mtodo.

La siguientes aristas ms pequeas son AB y BE, ambas con peso 7. AB se elige arbitrariamente, y se resalta. La arista BD se resalta en rojo, porque formara un ciclo ABD si se hubiera elegido.

El proceso contina marcando las aristas, BE con peso 7. Muchas otras aristas se marcan en rojo en este paso: BC (formara el ciclo BCE), DE (formara el ciclo DEBA), y FE (formara el ciclo FEBAD).

Finalmente, el proceso termina con la arista EG de peso 9, y se ha encontrado el rbol expandido mnimo.

Algoritmo de Floyd-Warshall En informtica, el algoritmo de Floyd-Warshall, descrito en 1959 por Bernard Roy, es un algoritmo de anlisis sobre grafos para encontrar el camino mnimo en grafos dirigidos ponderados. El algoritmo encuentra el camino entre todos los pares de vrtices en una nica ejecucin. El algoritmo de FloydWarshall es un ejemplo de programacin dinmica. Algoritmo El algoritmo de Floyd-Warshall compara todos los posibles caminos a travs del grafo entre cada par de vrtices. El algoritmo es capaz de hacer esto con slo V3 comparaciones (esto es notable

considerando que puede haber hasta V2 aristas en el grafo, y que cada combinacin de aristas se prueba). Lo hace mejorando paulatinamente una estimacin del camino ms corto entre dos vrtices, hasta que se sabe que la estimacin es ptima. Sea un grafo G con conjunto de vrtices V, numerados de 1 a N. Sea adems una funcin caminoMinimo(i,j,k) que devuelve el camino mnimo de i a j usando nicamente los vrtices de 1 a k como puntos intermedios en el camino. Ahora, dada esta funcin, nuestro objetivo es encontrar el camino mnimo desde cada i a cada j usando nicamente los vrtices de 1 hasta k + 1. Hay dos candidatos para este camino: un camino mnimo, que utiliza nicamente los vrtices del conjunto (1...k); o bien existe un camino que va desde i hasta k + 1, despus de k + 1 hasta j que es mejor. Sabemos que el camino ptimo de i a j que nicamente utiliza los vrtices de 1 hasta k est definido por caminoMinimo(i,j,k), y est claro que si hubiera un camino mejor de i a k + 1 a j, la longitud de este camino sera la concatenacin del camino mnimo de i a k + 1 (utilizando vrtices de (1...k)) y el camino mnimo de k + 1 a j (que tambin utiliza los vrtices en (1...k)).

Por lo tanto, podemos definir caminoMinimo(i,j,k) de forma recursiva:

Esta frmula es la base del algortimo Floyd-Warshall. Funciona ejecutando primero caminoMinimo(i,j,1) para todos los pares (i,j), usndolos para despus hallar caminoMinimo(i,j,2) para todos los pares (i,j)... Este proceso contina hasta que k = n, y habremos encontrado el camino ms corto para todos los pares de vrtices (i,j) usando algn vrtice intermedio. Pseudocodigo Convenientemente, cuando calculamos el k-esimo caso, se puede sobreescribir la informacin salvada en la computacin k -1. Esto significa que el algoritmo usa memoria cuadrtica. Hay que cuidar la inicializacin de las condiciones: 1 /* Suponemos que la funcin pesoArista devuelve el coste del camino que va de i a j 2 (infinito si no existe). 3 Tambin suponemos que n es el nmero de vrtices y pesoArista(i,i) = 0 4 */ 5 6 int camino[][]; 7 /* Una matriz bidimensional. En cada paso del algoritmo, camino[i][j] es el camino mnimo 8 de i hasta j usando valores intermedios de (1..k-1). Cada camino[i][j] es inicializado a 9 pesoArista(i,j) 10 */

11 12 procedimiento FloydWarshall () 13 para k: = 0 hasta n 1 14 para todo (i,j) en (0..n 1) 15 camino[i][j] = mn ( camino[i][j], camino[i][k]+camino[k][j]); Comportamiento con ciclos negativos Para que haya coherencia numrica, Floyd-Warshall supone que no hay ciclos negativos (de hecho, entre cualquier pareja de vrtices que forme parte de un ciclo negativo, el camino mnimo no est bien definido porque el camino puede ser infinitamente pequeo). No obstante, si hay ciclos negativos, Floyd-Warshall puede ser usado para detectarlos. Si ejecutamos el algoritmo una vez ms, algunos caminos pueden decrementarse pero no garantiza que, entre todos los vrtices, caminos entre los cuales puedan ser infinitamente pequeos, el camino se reduzca. Si los nmeros de la diagonal de la matriz de caminos son negativos, es condicin necesaria y suficiente para que este vrtice pertenezca a un ciclo negativo. Ejemplo Hallar el camino mnimo desde el vrtice 3 hasta 4 en el grafo con la siguiente matriz de distancias:

Aplicamos el algoritmo de Floyd-Warshall, y para ello en cada iteracin fijamos un vrtice intermedio.

1 Iteracin: nodo intermedio = 1 La matriz es simtrica, por lo que solamente har falta calcular el tringulo superior de las distancias. d23 = min(d23, d21 + d13) = 8 d24 = min(d24, d21 + d14) = 4 d25 = min(d25, d21 + d15) = 9 d26 = min(d26, d21 + d16) =

d34 = min(d34, d31 + d14) = 6 d35 = min(d35, d31 + d15) = 7 d36 = min(d36, d31 + d16) = 1 d45 = min(d45, d41 + d15) = d46 = min(d46, d41 + d16) = 4 d56 = min(d56, d51 + d16) = La matriz de distancia despus de esta iteracin es:

2 Iteracin: nodo intermedio = 2 d13 = min(d13, d12 + d23) = 5 d14 = min(d14, d12 + d24) = 1 d15 = min(d15, d12 + d25) = 12 d16 = min(d16, d12 + d26) = d34 = min(d34, d32 + d24) = 6 d35 = min(d35, d32 + d25) = 7 d36 = min(d36, d32 + d26) = 1 d45 = min(d45, d42 + d25) = 13 d46 = min(d46, d42 + d26) = 4 d56 = min(d56, d52 + d26) =

La matriz de distancia despus de esta iteracin es:

3 Iteracin: nodo intermedio = 3 d12 = min(d12, d13 + d32) = 3 d14 = min(d14, d13 + d34) = 1 d15 = min(d15, d13 + d35) = 12 d16 = min(d16, d13 + d36) = 6 d24 = min(d24, d23 + d34) = 4 d25 = min(d25, d23 + d35) = 9 d26 = min(d26, d23 + d36) = 9 d45 = min(d45, d43 + d35) = 13 d46 = min(d46, d43 + d36) = 4 d56 = min(d56, d53 + d36) = 8 La matriz de distancia despus de esta iteracin es:

4 Iteracin: nodo intermedio = 4

d12 = min(d12, d14 + d42) = 3 d13 = min(d13, d14 + d43) = 5 d15 = min(d15, d14 + d45) = 12 d16 = min(d16, d14 + d46) = 5 d23 = min(d23, d24 + d43) = 8 d25 = min(d25, d24 + d45) = 9 d26 = min(d26, d24 + d46) = 8 d35 = min(d35, d34 + d45) = 7 d36 = min(d36, d34 + d46) = 1 d56 = min(d56, d54 + d46) = 8 La matriz de distancia despus de esta iteracin es:

5 Iteracin: nodo intermedio = 5 d12 = min(d12, d15 + d52) = 3 d13 = min(d13, d15 + d53) = 5 d14 = min(d14, d15 + d54) = 1 d16 = min(d16, d15 + d56) = 5 d23 = min(d23, d25 + d53) = 8 d24 = min(d24, d25 + d54) = 4

d26 = min(d26, d25 + d56) = 8 d34 = min(d34, d35 + d54) = 6 d36 = min(d36, d35 + d56) = 1 d46 = min(d46, d45 + d56) = 4 La matriz de distancia despus de esta iteracin es:

6 Iteracin: nodo intermedio = 6 d12 = min(d12, d16 + d62) = 3 d13 = min(d13, d16 + d63) = 5 d14 = min(d14, d16 + d64) = 1 d15 = min(d15, d16 + d65) = 12 d23 = min(d23, d26 + d63) = 8 d24 = min(d24, d26 + d64) = 4 d25 = min(d25, d26 + d65) = 9 d34 = min(d34, d36 + d64) = 5 d35 = min(d35, d36 + d65) = 7 d45 = min(d45, d46 + d65) = 12 La matriz de distancia despus de esta iteracin es:

Ya se han hecho todas las iteraciones posibles. Por tanto, el camino mnimo entre 2 vrtices cualesquiera del grafo ser el obtenido en la matriz final. En este caso, el camino mnimo entre 3 y 4 vale 5. Anlisis Si utilizamos matrices booleanas, para encontrar todos los n2 de desde se necesita hacer 2 2n operaciones binarias. Debido a que empezamos con y computamos la secuencia de n matrices booleanas , , ..., , el nmero total de operaciones binarias es de . Por lo tanto, la complejidad del algoritmo es (n3) y puede ser resuelto por una mquina determinista de Turing en tiempo polinmico. Aplicaciones y generalizaciones El algoritmo de Floyd-Warshall puede ser utilizado para resolver los siguientes problemas, entre otros:

Camino mnimo en grafos dirigidos(algoritmo de Floyd). Cierre transitivo en grafos dirigidos (algoritmo de Warshall). Es la formulacin original del algoritmo de Warshall. El grafo es un grafo no ponderado y representado por una matriz booleana de adyacencia. Entonces la operacin de adicin es reemplazada por la conjuncin lgica(AND) y la operacin menor por la disyuncin lgica (OR). Encontrar una expresin regular dada por un lenguaje regular aceptado por un autmata finito (algoritmo de Kleene). Inversin de matrices de nmeros reales(algoritmo de Gauss-Jordan). Ruta optima. En esta aplicacin es interesante encontrar el camino del flujo mximo entre 2 vrtices. Esto significa que en lugar de tomar los mnimos con el pseudocodigo anterior, se coge el mximo. Los pesos de las aristas representan las limitaciones del flujo. Los pesos de los caminos representan cuellos de botella; por ello, la operacin de adicin anterior es reemplazada por la operacin mnimo. Comprobar si un grafo no dirigido es bipartito.

Implementacin del algoritmo de Floyd en Java

El algoritmo de Floyd intenta resolver el problema de encontrar el camino ms corto entre todos los pares de nodos o vrtices de un grafo. Esto es similar a construir una tabla con todas las distancias mnimas entre pares de ciudades de un mapa, indicando la ruta a seguir para ir de la primera ciudad a la segunda. Esto puede verse de la siguiente manera:

Sea G= (V, A) un digrafo en el cual cada arco tiene asociado un costo no negativo. El problema es hallar para cualquier par de vrtices (v, w) el camino ms corto de v a w. G= (V, A), V= {1,...,n} y C[i, j] es el costo del arco que va de i a j. El algoritmo calcula la serie de matrices Ak[i, j] significa el costo del camino ms corto que va de i a j y que no pasa por algn vrtice mayor que k. El objetivo es calcular An[i, j]

Adems de eso, se busca hallar tambin el camino ms corto entre cada par de nodos, imprimiendo as en el programa no solo la matriz final sino tambin dichos caminos. Solucin al problema La solucin al problema se puede dar aplicando el algoritmo de Floyd para encontrar las distancias y caminos mnimos entre nodos. Una forma de implementar el algoritmo de Floyd en java es como se muestra en el siguiente fragmento de cdigo. Se utiliz un enfoque dinmico, ya que se guardan valores en una matriz para luego reutilizarlos y no repetir operaciones. public String floyd(long[][] adyacencia) { int n=adyacencia.length; long D[][]=adyacencia; String enlaces[][]=new String [n][n]; String[][] aux_enlaces=new String[n][n]; }

El mtodo recibe una matriz, en este caso la matriz de adyacencia del grafo. Para calcular las distancias mnimas se crea una matriz D[][], la cual ir guardando los resultados que arroja el algoritmo de Floyd, y otra matriz que guardar los caminos mnimos llamada enlaces[][]. Los caminos mnimos se calculan, utilizando los diferentes k, que son guardados en la matriz enl_aux[][], y utilizada en el mtodo enlaces(). El mtodo enlaces, utiliza una llamada recursiva para recorrer la matriz de enlaces y arrojar el camino mnimo entre los nodos. Este resultado ser guardado en la matriz enlaces[i][j]. Limitaciones

Las limitaciones que se encontraron con el algoritmo no son muchas, mejor dicho, no se encontraron, a excepcin que cuando se va a resolver un grafo muy grande, ste no halla la respuesta porque se presenta un desborde de memoria, ya que debe iterar y almacenar demasiados valores. Complejidad temporal Este es el mtodo principal, es decir, el que halla la solucin del problema que se le plantee (la matriz de adyacencia):

TABLA 1. Calculo del T (n)

Instruccin

Tiem po

long[][] adyacencia

int n=adyacencia.length

long D[][]=adyacencia

String enlaces[][]=new String [n][n]

String[][] aux_enlaces=new String[adyacencia.length][adyacencia.length]

1 4n2 + 4n + 2

(1)for concatenados

String enl_rec=""

1 bn4 + an3 + 12n3 + 4n2

(2)for concatenados

+ 4n +2

enlaces (int i, int k, String[][] aux_enlaces,String enl_rec)

if(aux_enlaces[i][k].equals("")==true)

return "

enl_rec+=enlaces (i, Integer.parseInt(aux_enlaces[i][k].toString()),aux_enlaces,enl_rec)+(Integer.parseInt(aux_en an+b laces[i][k].toString())+1)+" , " T (n)=bn4 + an3 + 12n3 + 8n2 + 8n + 13 y O(n4)

Cdigo fuente Forma de compilar y ejecutar Para poder compilar y ejecutar el programa debe tener instalado en su computador el jdk de java 1.5 o una actualizacin ms reciente y adems debe tener el path de su sistema configurado con el JDK. Este programa est hecho en lenguaje Java, por lo que se puede compilar y ejecutar en cualquier IDE que tenga soporte JAVA; si usa Netbeans o Eclipse, debe primero crear un proyecto con el nombre que quiera, y crea tres clases con los correspondientes nombres usados en el cdigo fuente y lgicamente pega dicho cdigo en la clase. Si usa JCreator, puede bien sea, crear una nica clase con el nombre de Aplicacin y pega ah todo el cdigo fuente, o crea las tres clases con los nombres que son y pega el cdigo fuente correspondiente en cada clase. Tiempo empleado El tiempo que nos tardo desarrollar el programa fue aproximadamente 3 das, el primer da desarrollando el algoritmo de solucin, el segundo da desarrollando la interfaz grafica, y el tercero corrigiendo las excepciones que se pudieran presentar. Pruebas

Esta es la matriz de adyacencia de un grafo que puede ser utilizada para probar la efectividad del algoritmo: La i representa infinito.

Matriz de adyacencia

2 3

1 0

5 i

2 50

0 15

3 30

15

4 15

La respuesta es: Los caminos mnimos entre nodos son: De ( 1 a 2 ) = ( 1 , 2 ) De ( 1 a 3 ) = ( 1 , 2 , 4 , 3 ) De ( 1 a 4 ) = ( 1 , 2 , 4 ) De ( 2 a 1 ) = ( 2 , 4 , 1 ) De ( 2 a 3 ) = ( 2 , 4 , 3 ) De ( 2 a 4 ) = ( 2 , 4 ) De ( 3 a 1 ) = ( 3 , 1 ) De ( 3 a 2 ) = ( 3 , 1 , 2 ) De ( 3 a 4 ) = ( 3 , 4 )

De ( 4 a 1 ) = ( 4 , 1 ) De ( 4 a 2 ) = ( 4 , 1 , 2 ) De ( 4 a 3 ) = ( 4 , 3 ) Conclusiones

Con las herramientas adecuadas y unos buenos fundamentos en programacin, adems de tener un conocimiento en grafos, se podra concluir que el algoritmo es fcil de implementar. Para hallar la solucin ptima es mucho mejor usar el enfoque dinmico, ya que ste no repite operaciones y acelera un poco el proceso de solucin. El algoritmo tiene una desventaja, debido a su enfoque dinmico, realiza un uso masivo de memoria, lo cual puede ser inconveniente.

Floyd-Warshall Algorithm in C

The following is a C code implementation of the Floyd-Warshall algorithm for solving the all-pairs shortest path problem. The code is not guaranteed to run correctly in all cases as I have only tested it on my system, but if it does not, please let me know! // Floyd-Warshall algorithm // // solves the all-pairs shortest path problem using Floyd-Warshall algorithm // inputs: nn, number of nodes // connectivity matrix cmat, where 0 means disconnected // and distances are all positive. array of doubles of // length (nn*nn). // outputs: // dist_mat - shortest path distances(the answer) // pred_mat - predicate matrix, useful in reconstructing shortest routes // Note that the caller should provide empty pointers as this // function will handle the malloc() calls. void fwarsh(int nn, double *cmat, double **dist_mat, int **pred_mat) { double *dist; int *pred; int i,j,k; //loop counters //initialize data structures dist = (double *)malloc(sizeof(double) * nn * nn); pred = (int *)malloc(sizeof(int) * nn * nn);

memset(dist, 0, sizeof(double)*nn*nn); memset(pred, 0, sizeof(int)*nn*nn); //algorithm initialization for (i=0; i < nn; i++) { for (j=0; j < nn; j++) { if (cmat[i*nn+j] != 0.0) dist[i*nn+j] = cmat[i*nn + j]; else dist[i*nn+j] = HUGE_VAL; //disconnected if (i==j) //diagonal case dist[i*nn+j] = 0; if ((dist[i*nn + j] > 0.0) && (dist[i*nn+j] < HUGE_VAL)) pred[i*nn+j] = i; } } //Main loop of the algorithm for (k=0; k < nn; k++) { for (i=0; i < nn; i++) { for (j=0; j < nn; j++) { if (dist[i*nn+j] > (dist[i*nn+k] + dist[k*nn+j])) { dist[i*nn+j] = dist[i*nn+k] + dist[k*nn+j]; pred[i*nn+j] = k; //printf("updated entry %d,%d with %d\n", i,j, dist[i*nn+j]); } } } } /* //Print out the results table of shortest distances for (i=0; i < nn; i++) { for (j=0; j < nn; j++) printf("%g ", dist[i*nn+j]); printf("\n"); } */ //now set the dist and pred matrices for the calling function //but do some checks because we allow NULL to be passed if the user //doesn't care about one of the results. if (dist_mat)

*dist_mat = dist; else free(dist); if (pred_mat) *pred_mat = pred; else free(pred); return; } //end of fwarsh()

1.9 LOCURA INSTANTNEA Es un juego formado por 4 cubos, cada una de cuyas caras est pintada de uno de 4 colores: rojo, blanco, azul, verde (R, B, A, V).

El problema consiste en apilar los cubos, uno sobre otro, de modo que uno vea los 4 colores desde el frente, por detrs, por la izquierda o por la derecha. Ejemplo: Determine una solucin del juego de locura instantnea, cuya informacin est dada por el siguiente grafo:

RB BV VA AR

AB AV VB RR Cada arista debe tener grado 2. Cada cubo debe representarse mediante una arista exactamente una vez en cada grfica. Las dos grficas no deben tener aristas en comn. tPara obtener una solucin primero trazamos una grfica G que representa todas las caras de todos los cubos. Los vrtices de G representan los cuatro colores y una arista con etiqueta i conecta dos vrtices (colores) si las caras opuestas i tienen dichos colores. No es conveniente el mtodo prueba error. Mejor busque dos subgrficas que cumplan las condiciones pedidas.

Você também pode gostar