elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado:


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  Inicializar matrices en Floyd
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Inicializar matrices en Floyd  (Leído 7,201 veces)
Archivel

Desconectado Desconectado

Mensajes: 4


Ver Perfil
Inicializar matrices en Floyd
« en: 21 Agosto 2010, 19:55 pm »

Hola, aunque quizá esto tiene más que ver con las matematicas que la programacion en si, estoy implementando un TAD grafo y se me plantea una duda.

Tengo que programar el algoritmo de Floyd para que me de la matriz de distancias (esto ok) y la matriz de nodos.

Os expongo graficamente mi duda con la matriz de nodos, que no se me da muy bien explicarme:



Como debo inicializar las casillas de la matriz en las que pongo interrogacion?? Al no haber un camino directo entre esos nodos, no tengo claro como iniciarlizarlas y no he encontrado ningun ejemplo que me lo aclare.

Gracias por vuestra ayuda!


En línea

ghastlyX
Ex-Staff
*
Desconectado Desconectado

Mensajes: 1.900



Ver Perfil
Re: Inicializar matrices en Floyd
« Respuesta #1 en: 22 Agosto 2010, 17:09 pm »

Supongo que por matriz de nodos te referirás a la matriz que te permita reconstruir cada camino mínimo. Si esto es lo que te refieres, la forma típica de hacerlo es que una vez acabado el algoritmo, la posición M(i,j) de la matriz te diga el penúltimo nodo del menor camino de i a j, llamémosle k, para luego consultar M(i,k) y así hasta llegar al nodo i.

Para ello, normalmente se inicializa poniendo lo que quieras entre nodos que no tengan aristas (puesto que si hay un camino se sobreescribirá y si no lo hay lo verás en la matriz de distancias, por lo que ignorarás lo que tengas en esta).

En tu ejemplo, la matriz de distancias inicial sería así:
0 3 INF
3 0 5
INF 5 0

Y la matriz de antecesores sería:
A A X
B B B
X C C

Donde X quiere decir que puedes poner lo que quieras.

Si no me he equivocado al picarlo rápido, el código sería así en C++:
Código
  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4.  
  5. const int INF = 1000000000;
  6.  
  7. int main() {
  8.    int n, m; //nodos, aristas
  9.    cin >> n >> m;
  10.    vector<vector<int> > G(n, vector<int> (n, INF)); //Matriz de distancias
  11.    vector<vector<int> > A(n, vector<int> (n, -1)); //Matriz de antecesores
  12.    for (int i = 0; i < n; ++i) G[i][i] = 0;
  13.    for (int i = 0; i < n; ++i) A[i][i] = i;
  14.    for (int i = 0; i < m; ++i) { //Lectura de aristas
  15.        int a, b, c; //extremos y coste
  16.        cin >> a >> b >> c;
  17.        G[a][b] = G[b][a] = c;
  18.        A[a][b] = a;
  19.        A[b][a] = b;
  20.    }
  21.    cout << "Estado inicial de las matrices" << endl;
  22.    cout << "Matriz de distancias:" << endl;
  23.    for (int i = 0; i < n; ++i) {
  24.        for (int j = 0; j < n; ++j) {
  25.            cout << G[i][j] << '\t';
  26.        }
  27.        cout << endl;
  28.    }
  29.    cout << "Matriz de antecesores:" << endl;
  30.    for (int i = 0; i < n; ++i) {
  31.        for (int j = 0; j < n; ++j) {
  32.            cout << A[i][j] << '\t';
  33.        }
  34.        cout << endl;
  35.    }
  36.    //Floyd-Warshall
  37.    for (int k = 0; k < n; ++k) {
  38.        for (int i = 0; i < n; ++i) {
  39.            for (int j = 0; j < n; ++j) {
  40.                if (G[i][j] > G[i][k] + G[k][j]) {
  41.                    G[i][j] = G[i][k] + G[k][j];
  42.                    A[i][j] = A[k][j];
  43.                    A[j][i] = A[k][i];
  44.                }
  45.            }
  46.        }
  47.    }
  48.    cout << endl;
  49.    cout << "Estado final de las matrices" << endl;
  50.    cout << "Matriz de distancias:" << endl;
  51.    for (int i = 0; i < n; ++i) {
  52.        for (int j = 0; j < n; ++j) {
  53.            cout << G[i][j] << '\t';
  54.        }
  55.        cout << endl;
  56.    }
  57.    cout << "Matriz de antecesores:" << endl;
  58.    for (int i = 0; i < n; ++i) {
  59.        for (int j = 0; j < n; ++j) {
  60.            cout << A[i][j] << '\t';
  61.        }
  62.        cout << endl;
  63.    }
  64. }
  65.  

Y ejecutándolo con tu grafo (cambiando los nombres de los nodos, en vez de A B C, 0 1 2), es decir, poniendo como entrada:
Código:
3 2
0 1 3
1 2 5
Da la siguiente salida:
Código:
Estado inicial de las matrices
Matriz de distancias:
0       3       1000000000
3       0       5
1000000000      5       0
Matriz de antecesores:
0       0       -1
1       1       1
-1      2       2

Estado final de las matrices
Matriz de distancias:
0       3       8
3       0       5
8       5       0
Matriz de antecesores:
0       0       1
1       1       1
1       2       2



En línea

Archivel

Desconectado Desconectado

Mensajes: 4


Ver Perfil
Re: Inicializar matrices en Floyd
« Respuesta #2 en: 28 Agosto 2010, 18:34 pm »

Hola,

En primer lugar lo siento por no haber contestado antes, se me juntan los ultimos dias del curro de verano con las asignaturas de septiembre y voy agobiadisima.

Probé el código (mil gracias ghastlyX) y pude adaptarlo a mi problema a las mil maravillas.

Mi codigo chequea el grafo para saber el numero de nodos y entre cuales de ellos existe arista y cual es su peso. A partir de ahi calcula las dos matrices a la perfeccion  ;D

Solo me queda una duda, y es en grafos mas complejos, donde el camino puede ser mas largo (ejemplo A -> C -> D -> H) como rescato ese camino a partir de la matriz?

Gracias de nuevo y un saludo!!
En línea

ghastlyX
Ex-Staff
*
Desconectado Desconectado

Mensajes: 1.900



Ver Perfil
Re: Inicializar matrices en Floyd
« Respuesta #3 en: 28 Agosto 2010, 19:38 pm »

Tal y como he puesto el código, si M es la matriz de antecesores y u, v son dos nodos cualquiera tales que existe un camino entre ellos (la distancia mínima entre ellos tras hacer Floyd-Warshall no es INF), M[ u][ v] indica el penúltimo nodo del camino mínimo entre u y v. Por ejemplo, si M[ u][v] vale k, significa que el menor camino de u a v será:
u -> (camino entre u y k) -> k -> v.

Y dicho camino entre u y k naturalmente será el mínimo camino entre u y k, por lo que volviendo a consultar la matriz de antecesores podemos ir creando el camino, hasta llegar al origen. La siguiente función, te devolvería el camino mínimo entre s y t con el código anterior que puse:
Código
  1. void camino(int s, int t, vector<vector<int> >& A) {
  2.    if (t != s) camino(s, A[s][t], A);
  3.    cout << t << " ";
  4. }

Por ejemplo, en el caso de un grafo más complejo como tú decías, si tienes el siguiente grafo (pongo la entrada como la recibe mi programa):
Código:
5 7
0 1 1
0 2 4
0 3 3
1 3 1
2 3 1
2 4 1
3 4 5

Es evidente que el camino mínimo entre los nodos 0 y 4 tiene coste 4 y pasa por todos los nodos. Si llamas a la función que te he puesto:
Código
  1. cout << "Camino de nodo 0 a nodo 4" << endl;
  2. camino(0, 4, A);

Devuelve la siguiente salida:
Código:
Camino de nodo 0 a nodo 4
0 1 3 2 4

Que es efectivamente el camino mínimo entre 0 y 4.

En línea

Archivel

Desconectado Desconectado

Mensajes: 4


Ver Perfil
Re: Inicializar matrices en Floyd
« Respuesta #4 en: 29 Agosto 2010, 12:21 pm »

Gracias a ti soy una experta en matematicas!! jejejeje.

Lastima que en programacion pura aun ande un poco perdida.

El algoritmo me funciona perfectamente y adaptandolo a mi trabajo tuve un problema.

La clase Grafo con la que trabajo tiene definido el metodo Grafo::floyd() como una funcion privada que ni recibe parametros ni devuelve nada, simplemente internamente calcula las estructuras D y P y listo.

El problema me viene al implementar el metodo Grafo::camino(Nodo *origen, Nodo *destino) ya que desde ese metodo no puedo acceder a las estructuras D y P de floyd().

Alguna idea?

El codigo lo tengo totalmente planteado, salvo ese "pequeño" detalle de como acceder a las estructuras D y P desde camino.

Un saludo!


EDITO: Yo no he podido usar la libreria vector del STL, ya que tengo prohibido STL.

Lo que hice fue hacer las matrices de la siguiente manera:

Código:
        int **D, **P;
        D = new int* [fils];
        for(int i=0;i<fils;i++){
                D[i] = new int [cols];
        }
        P = new int* [fils];
        for(int i=0;i<fils;i++){
                P[i] = new int [cols];
        }
« Última modificación: 29 Agosto 2010, 12:24 pm por Archivel » En línea

Archivel

Desconectado Desconectado

Mensajes: 4


Ver Perfil
Re: Inicializar matrices en Floyd
« Respuesta #5 en: 30 Agosto 2010, 18:09 pm »

A veces la solución es tan obvia que pasamos de ella por sencilla.

Solo tuve que declarar D y P fuera del metodo y listo  ;D ;D ;D
En línea

Dashiel

Desconectado Desconectado

Mensajes: 7


Ver Perfil
Re: Inicializar matrices en Floyd
« Respuesta #6 en: 11 Julio 2013, 00:55 am »

Aqui te dejo un codigo del algoritmo de floyd para usar facil t rapido ,,
solo te faltaria inicializar las matrices D (costo) y P (predecesores) que es muy sencilo o pasarlas como referencia ...
la cantidad es la cantidad maxima de la matriz que creastes!


 
Código
  1. Void Floyd()
  2.    {
  3.      for(int i=0; i< cantidad;i++)
  4.       for(int j=0; j<cantidad; j++)
  5.        for(int k=0; k<cantidad; k++)
  6.      if(matriz[j][k]>(matriz[j][i]+ matriz[i][k]))
  7.       {
  8.         costos[j][k]=matriz[j][i]+ matriz[i][k];
  9.         predecesor[j][k];
  10.       }
  11.    }



ya lo otro seria implemenar el agoritmo que busque el camino minimo usando estas matrices. Si tienes duda en esto te puedo ayudar!
saludos desde cuba
« Última modificación: 11 Julio 2013, 00:58 am por Dashiel » En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Inicializar contador
PHP
Leber 3 2,758 Último mensaje 6 Noviembre 2007, 13:51 pm
por Red Mx
Inicializar HDD
Hardware
Polydeuces 5 12,133 Último mensaje 9 Octubre 2012, 03:04 am
por _Slash_
Camino minimo en floyd!
Programación C/C++
Dashiel 9 3,209 Último mensaje 9 Julio 2013, 18:30 pm
por Dashiel
ayuda con floyd
Programación C/C++
nolasco281 2 1,685 Último mensaje 16 Junio 2014, 11:04 am
por nolasco281
Algoritmo de Floyd Warshall
Programación C/C++
Luisyoxd 1 2,879 Último mensaje 6 Marzo 2020, 12:42 pm
por 98Fran
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines