Algoritmos de grafos en C++: Dijkstra, Kruskal, DFS, BFS y ordenamiento topológico

Informática5,13 KB

Algoritmos de grafos en C++

A continuación se presentan implementaciones en C++ de algoritmos clásicos sobre grafos: el algoritmo de Dijkstra, el algoritmo de Kruskal, los recorridos DFS y BFS, y el ordenamiento topológico.

1. Algoritmo de Dijkstra

Calcula las distancias mínimas desde un vértice inicial a todos los demás vértices de un grafo con pesos no negativos, utilizando una cola de prioridad.

void dijkstra(vector<vector<pair<int, int>>> &grafo, vector<int> &dist, int inicio)
{
    dist[inicio] = 0;
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> colaprio;
    colaprio.push(make_pair(0, inicio));
    while (!colaprio.empty())
    {
        int u = colaprio.top().second;
        colaprio.pop();
        vector<pair<int, int>>::iterator it;
        for (it = grafo[u].begin(); it != grafo[u].end(); it++)
        {
            int v = it->first;
            int peso = it->second;
            if (dist[v] > dist[u] + peso)
            {
                dist[v] = dist[u] + peso;
                colaprio.push(make_pair(dist[v], v));
                MostrarCola(colaprio);
                MostrarVector(dist, inicio);
            }
        }
    }
}

2. Algoritmo de Kruskal

Construye un árbol de expansión mínima ordenando las aristas por peso y uniendo vértices mediante la estructura Union-Find.

void kruskal()
{
    mostrar(); cout << endl;
    sort(aristas.begin(), aristas.end(), compararAristas);
    mostrar(); cout << endl;
    vector<int> padres(numVertices);
    for (int i = 0; i < numVertices; i++)
    {
        padres[i] = i;
    }
    vector<vector<int>> arbolExpansion;
    for (const Arista& arista : aristas)
    {
        int origen = arista.origen;
        int destino = arista.destino;
        int raizOrigen = encontrarRaiz(padres, origen);
        int raizDestino = encontrarRaiz(padres, destino);
        if (raizOrigen != raizDestino)
        {
            arbolExpansion.push_back({ origen, destino });
            unirConjuntos(padres, raizOrigen, raizDestino);
        }
    }
    for (const auto& arista : arbolExpansion)
    {
        cout << arista[0] << " - " << arista[1] << endl;
    }
}

3. Búsqueda en profundidad (DFS) con ordenamiento topológico

Recorre el grafo en profundidad y apila los vértices al finalizar su exploración; el resultado invertido corresponde a un orden topológico.

void dfs(int v, vector<int> &visitado, stack<int> &Pila, const vector<vector<pair<int, int>>> &grafo)
{
    visitado[v] = 1;
    for (const auto& arista : grafo[v])
    {
        int u = arista.first; // Obtener el destino
        if (!visitado[u])
        {
            cout << "bajada v : " << v << " - ";
            Mostrar(Pila);
            dfs(u, visitado, Pila, grafo);
            cout << "subida v : " << v << " - ";
            Mostrar(Pila);
        }
    }
    Pila.push(v);
}

void ordenTopologico(int V, const vector<vector<pair<int, int>>> &grafo)
{
    stack<int> Pila;
    vector<int> visitado(V, 0);
    for (int i = 0; i < V; ++i)
    {
        if (!visitado[i]) dfs(i, visitado, Pila, grafo);
    }
    cout << "Solución" << endl;
    Mostrar(Pila);
}

4. Implementación con lista de adyacencia

Se define la inserción de aristas en una lista de adyacencia y dos recorridos: DFS iterativo con pila y BFS con cola.

void agregarArista(int origen, int destino)
{
    LAdyac[origen].push_back(destino);
}

void DFS(int verticeInicial)
{
    vector<int> visitado(Nver, 0);
    stack<int> pila;
    visitado[verticeInicial] = 1;
    pila.push(verticeInicial);
    while (!pila.empty())
    {
        int verticeActual = pila.top();
        pila.pop();
        cout << verticeActual << " ";
        for (int i = LAdyac[verticeActual].size() - 1; i >= 0; i--)
        {
            int adyacente = LAdyac[verticeActual][i];
            if (!visitado[adyacente])
            {
                visitado[adyacente] = 1;
                pila.push(adyacente);
            }
        }
    }
}

void BFS(int verticeInicial)
{
    vector<int> visitado(Nver, 0);
    queue<int> cola;
    visitado[verticeInicial] = 1;
    cola.push(verticeInicial);
    while (!cola.empty())
    {
        int verticeActual = cola.front();
        cola.pop();
        cout << verticeActual << " ";
        for (int adyacente : LAdyac[verticeActual])
        {
            if (!visitado[adyacente])
            {
                visitado[adyacente] = 1;
                cola.push(adyacente);
            }
        }
    }
}

Descargar

PDF Word HTML