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

 

 


Tema destacado: Como proteger una cartera - billetera de Bitcoin


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Algoritmo de Dijkstra
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Algoritmo de Dijkstra  (Leído 3,982 veces)
castrokin

Desconectado Desconectado

Mensajes: 2


Ver Perfil
Algoritmo de Dijkstra
« en: 1 Agosto 2021, 02:39 am »

Hola Chicos espero puedan ayudarme con esta asignación

Se me pide saber la ruta más corta desde el nodo O al nodo T. Los números que se muestran en las
aristas representan la distancia entre los nodos.



Debo elaborar un programa en C++ que encuentre la ruta más corta entre los nodos O y T utilizando el algoritmo de Dijkstra.

este es mi código

Código:
#include <iostream>
#include <queue>
#include <vector>
#define MAXV 100 // Maxima cantidad de vertices.
#define oo 0x3f3f3f3f // Nuestro valor infinito.
using namespace std;


struct Edge
{
int node; // El nodo destino de la arista.
int cost; // El costo de la arista.
Edge(int _node, int _cost) : node(_node), cost(_cost) {} // Constructor parametrizado.
Edge() : node(-1), cost(-1) {} // Constructor por defecto.
};

struct Graph
{
vector<Edge> G[MAXV]; // Lista de adyacencias.
int V; // Cantidad de vertices.
int E; // Cantidad de aristas.
};

struct State
{
int node; // El nodo actual.
int cost; // El costo del camino.
State(int _node, int _cost) : node(_node), cost(_cost) {} // Constructor parametrizado.
bool operator <(const State &b) const // Sobrecarga del operador de prioridad <.
{
return cost > b.cost;
}
};

int algoritmo(const int begin, const int end, const Graph graph)
{
priority_queue<State> pq; // La cola de prioridad.
vector<int> Dist(graph.V, oo); // La distancia hacia todos los vertices. Inicialmente para cada vertice su valor es infinito.
vector<bool> mark(graph.V, false); // Este arreglo nos permitira determinar los nodos procesados.

Dist[begin] = 0; // Valor inicial del vertice de partida.
pq.push(State(begin, 0)); // Agregamos el primer elemento, que no es mas que el vertice de partida.
while(!pq.empty()) // Mientras existan vertices por procesar.
{
State st = pq.top(); pq.pop(); // Se desencola el elemento minimo.
mark[st.node] = true; // Se marca el nodo como visitado.
if (st.node == end)
return st.cost; // Retornamos el valor del camino, hemos llegado al vertice destino.

int T = (int)graph.G[st.node].size();
for(int i = 0; i < T; ++i) // Se recorren las adyacencias de "a".
{
// Si no ha sido procesado el vertice "vi" y la distancia hacia "vi" es menor a la distancia
// en Dist entonces hemos encontrado un camino mas corto a "vi".
if (!mark[graph.G[st.node][i].node] && ((Dist[st.node] + graph.G[st.node][i].cost) < Dist[graph.G[st.node][i].node]))
{
Dist[graph.G[st.node][i].node] = st.cost + graph.G[st.node][i].cost;
pq.push(State(graph.G[st.node][i].node, st.cost + graph.G[st.node][i].cost));
}
}
}
return -1; // Si no se puede llegar al destino, retornar -1.
}

struct Programa
{
int V, E;
int comienzo, fin;
void definirGrafo(Graph& graph)
{
cout << "Ingrese Cantidad de Vertices: " << endl;
cin >> V;
cout << "Ingrese Cantidad de Aristas: " << endl;
cin >> E;

graph.V = V;
graph.E = E;
}
void cargarGrafo(Graph & graph)
{
for (int i = 0; i < E; ++i)
{
int Origen, Destino, Peso;
cout << "Ingrese Origen: " << endl;
cin >> Origen;
cout << "Ingrese Destino: " << endl;
cin >> Destino;
cout << "Ingrese Peso de la Arista: " << endl;
cin >> Peso;

// Insertamos la arista dos veces, ya que nuestro grafo es un grafo no dirigido.
graph.G[Origen].push_back(Edge(Destino, Peso));
graph.G[Destino].push_back(Edge(Origen, Peso));
}
}
void Dijkstra(Graph graph)
{
cout << "Ingrese Vertice Inicial: " << endl;
cin >> comienzo;
cout << "Ingrese Vertice Final: " << endl;
cin >> fin;
int n = algoritmo(comienzo, fin, graph);
cout << "Longitud del Camino mas Corto: " << n << endl;
}
};

int main()
{
bool out=false;
char salir;

Programa programa; //TAD
Graph graph; // Grafo.

cout << "Algoritmo de Dijkstra en C++" << endl;

while (!out)
{
programa.definirGrafo(graph); //Se define cantidad de vertices y cantidad de aristas del grafo
programa.cargarGrafo(graph); //Se cargan las aristas del Grafo
programa.Dijkstra(graph); //Se aplica el algoritmo de Dijkstra

//Desea Salir?
cout << "Salir? (S/N)" << endl;
cin >> salir;
if (salir == 'S')
{
out = true;
}
}
}

Mi duda es

Sera este el mejor enfoque para darle o ustedes creen que se puede cambiar algo

Muchas gracias a todos


En línea

fzp

Desconectado Desconectado

Mensajes: 130


Ver Perfil
Re: Algoritmo de Dijkstra
« Respuesta #1 en: 6 Agosto 2021, 09:15 am »

Creo que el programa no funciona del todo correctamente. O bien puede ser que no esté hecho para todo el campo de los distintos tipos de grafo y algunos que yo he mirado se salen del campo de aplicación para los que el programa es válido.

Según me parece ver, cuando existen tramos lineales en los grafos, el programa se pierde.

Por ejemplo el primero de los dos siguientes: un enlace lineal de nodos. Ya sé que es obvio y que para ese caso no hay que pasar el programa, pero lo puse para ver que tal iba. El segundo caso también es obvio, aunque parece que da pistas sobre que no va bien la cosa cuando hay ramas lineales.




Los dos ejemplos siguientes también se ve que hay algo que se escapa. El D) podría resolverse igualmente calculando el trozo 3-4 a mano y usar el programa para el triángulo. El C) ya da idea de que en casos más complicados podría no funcionar bien la implementación del algoritmo. Desde luego en un caso real se podría descomponer el grafo en trozos, calculando los tramos lineales a mano, y los compactos por programa y sumando después. Pero eso implica tener el grafo a la vista, tener delante la representación visual del grafo. Cuando primero se hace el grafo a papel y luego se programa está bien. Pero ¿y si fuese un grafo procedente de la salida de otra aplicación, incluso con muchos nodos y aristas? En ese caso hacer primero la representación gráfica para hacer por separado los tramos lineales podría no ser viable, y sería deseable que el programa fuera capaz por sí mismo de calcular los tramos lineales sin problemas.





Por último otro caso en que hay dos zona más compactas unidas por un tramo lineal. Aquí ya no es que calcue mal; el programa directamente se para y da el mensaje:

nunmap_chunk(): invalid pointer
Abortado ('core' generado)




No he dado ninguna solución, pero por lo menos he ayudado a testear el programa. Igual, ya digo, es que el programa no está pensado para contemplar esos casos.

Se me olvidaba, en todos los casos se trataba de calcular entre el nudo inicial el de numeración más baja ( el 1) y como final el de numeración más alta de cada caso.


« Última modificación: 6 Agosto 2021, 09:18 am por fzp » En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Algoritmo de Dijkstra en Visual Basic
Programación Visual Basic
laukibuk 4 13,581 Último mensaje 17 Enero 2008, 07:32 am
por cobein
Algoritmo para un ejercicio; ¿Doble dijkstra?
Programación General
astinx 2 3,693 Último mensaje 16 Febrero 2012, 19:27 pm
por astinx
[Grafo] Base para el Algoritmo de Dijkstra
Programación C/C++
AlbertoBSD 1 3,222 Último mensaje 8 Agosto 2016, 05:01 am
por class_OpenGL
Auxilio con ALGORITMO DE DIJKSTRA!!!!! :'c
Programación C/C++
axel19 1 2,472 Último mensaje 3 Junio 2018, 10:23 am
por MAFUS
Algoritmo Dijkstra
Programación C/C++
castrokin 0 2,034 Último mensaje 6 Marzo 2022, 02:56 am
por castrokin
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines