C ++ implementa el algoritmo de ruta más corta (algoritmo de Dijkstra)

0Introducción

El algoritmo de Dijkstra es un algoritmo que calcula el camino más corto desde un vértice al resto del vértice. Utiliza una estrategia codiciosa y utiliza la amplitud primero en su implementación. Este algoritmo a menudo se aprende y se olvida, así que escribe un blog para resolverlo por completo.

1 Introducción a los pasos de cálculo

Los pasos de cálculo de Dijkstra no son difíciles, como sigue

(1)设置一个集合表示已经标记过的节点,初始化为空
(2)使用一个数组d记录所有节点与源节点s的距离,初始化d[s] = 0,其余设置为INF
(3)循环n次
{
	在未标记的节点中,选出d值最小的节点x;
	将x加入标记过节点的集合;
	对于从x出发的所有边(x,y),更新d[y] = min(d[y],d[x]+w(x,y))
}

Este principio no es difícil. Creo que los lectores pueden practicarlo varias veces contra el libro de texto de teoría de grafos. Implementémoslo junto con un tema específico sobre Leetcode.

2 Código de combate

La siguiente es la raíz de Leetcode743. Esta pregunta es una aplicación típica del algoritmo de Dijkstra. La pregunta no es difícil. Utilice el algoritmo de Dijkstra para calcular la distancia mínima desde el nodo fuente a los nodos restantes. Finalmente, regrese al valor máximo del nodo. Si este gráfico no es un gráfico conectado, devuelva -1.

Hay N nodos de red, etiquetados de 1 a N.
Dada una lista de tiempos, representa el tiempo de tránsito de la señal que pasa por el borde dirigido. veces [i] = (u, v, w), donde u es el nodo de origen, v es el nodo de destino y w es el tiempo para que una señal pase del nodo de origen al nodo de destino.
Ahora, enviamos una señal desde algún nodo K. ¿Cuánto tardan todos los nodos en recibir la señal? Si todos los nodos no pueden recibir la señal, devuelve -1.
Entrada: tiempos = [[2,1,1], [2,3,1], [3,4,1]], N = 4, K = 2
Salida: 2
Inserte la descripción de la imagen aquí

Para la realización del algoritmo de Dijkstra, el primer problema para resolver el problema es establecer una gráfica. Para el mapeo, usamos el método de lista de adyacencia, para cada punto, el punto conectado y el peso. En la implementación, lo abstraemos como un borde, usando una estructura Edge, donde u, vyd son el nodo de origen, el nodo de destino y el peso a su vez.

    struct Edge
    {
    
    
        int u,v,d;
        Edge(int from,int to,int dis)
            :      u(from),
                   v(to),
                   d(dis)
        {
    
    
        }
    };

Por lo tanto, cuando construimos un gráfico, usamos un vector<Edge> edgesborde de registro, cuando construimos un gráfico usando la tabla de adyacencia, es suficiente registrar el subíndice del borde donde se encuentra el nodo fuente.
Una vez completado el dibujo, use BFS para implementar los pasos de cálculo de la parte principal. Vale la pena señalar que hay un paso en el paso de cálculo. 在未标记的节点中,选出d值最小的节点x;Para este paso, podemos usar una cola de prioridad para optimizarlo. U es el nodo a marcar, y d es el mismo La distancia del nodo de origen. Aquí está sobrecargado <para que se clasifique en orden ascendente en la cola de prioridad.

    struct heapNode
    {
    
    
        int u,d;
        bool operator < (const heapNode& rhs) const
        {
    
    
            return d > rhs.d;
        }
    };

Echemos un vistazo a todo el código.

class Solution {
    
    
public:
    struct Edge
    {
    
    
        int u,v,d;
        Edge(int from,int to,int dis)
            :      u(from),
                   v(to),
                   d(dis)
        {
    
    
        }
    };
    struct heapNode
    {
    
    
        int u,d;
        bool operator < (const heapNode& rhs) const
        {
    
    
            return d > rhs.d;
        }
    };
    int networkDelayTime(vector<vector<int>>& times, int N, int K) 
    {
    
    
        priority_queue<heapNode> que;
        vector<Edge> edges;
        vector<vector<int>> g(N,vector<int>());
        vector<int> d(N,INT_MAX);
        d[K-1] = 0;
        vector<int> visited(N,0);
        for(int i = 0; i < times.size();++i)//建图
        {
    
    
            edges.push_back(Edge{
    
    times[i][0]-1,times[i][1]-1,times[i][2]});
            g[times[i][0]-1].push_back(edges.size()-1);
        }
        que.push(heapNode{
    
    K-1,0});//先把源节点加进去
        while(!que.empty())
        {
    
    
            heapNode node = que.top();
            que.pop();
            if(visited[node.u])
                continue;
            visited[node.u] = 1;//标记
            for(int i = 0; i < g[node.u].size(); ++i)
            {
    
    
                Edge &edge = edges[g[node.u][i]];
                if(d[edge.v] > d[edge.u] + edge.d)//更新权值
                {
    
    
                    d[edge.v] = d[edge.u] + edge.d;
                    que.push(heapNode{
    
    edge.v,d[edge.v]});
                }
            }
        }
        int result = -1;
        for(int i = 0; i < d.size(); ++i)
        {
    
    
            if(d[i] > result)
                result = d[i];
        }
        return result == INT_MAX ? -1 : result;//判断是否是连通图
    }
};

Supongo que te gusta

Origin blog.csdn.net/MoonWisher_liang/article/details/108062789
Recomendado
Clasificación