📜  算法|图最短路径|问题15(1)

📅  最后修改于: 2023-12-03 15:27:25.897000             🧑  作者: Mango

算法|图最短路径|问题15

问题描述

给定一个带权有向图,求从某个源点到其它所有点的最短路径。

解决方案

最短路径算法是图论中的一个经典问题,它是指在加权有向图或无向图中,求从一个顶点出发到其它顶点的最短路径。最短路径算法是解决该问题的有效方法。

在最短路径算法中,我们使用广度优先搜索和贪心算法等方法来找到从源节点到目标节点的最短路径。

Dijkstra算法

Dijkstra算法是解决最短路径问题的一个贪心算法。其基本思想是:设置一个数组dist,dist[i]表示当前已知从源点到i点的最短距离,对于每一个节点,如果存在一条从源节点到该节点的边,则更新dist数组中该节点的值。

Dijkstra算法使用一个优先队列来存储待处理的节点。每次从队列中取出距离源点最近的节点,更新以其为起点的所有能够到达的节点的距离值。当此节点相关的所有边都被处理完,即该节点的距离值确定,则将其从优先队列中删除。直到队列为空时,算法结束。

Bellman-Ford算法

Bellman-Ford算法是另一种解决最短路径问题的算法。它是一种动态规划的方法,可以处理有负权重的图。

Bellman-Ford算法的基本思想是:设置一个数组dist,dist[i]表示当前已知从源点到i点的最短距离,对于每一个节点,遍历每条边,如果存在从源节点到该节点的更短路径,则更新dist数组中该节点的值。

使用Bellman-Ford算法,需要遍历整张图V次,其中V是图中节点的数量,因为最短路径不可能超过V条边。如果在第V次遍历后,dist数组仍然可以被更新,则说明该图存在了一个负环。负环是指一个环,在环中所有边的权值之和为负数。

代码实现
Dijkstra算法实现
public void dijkstra(int[][] graph, int src) {
    int V = graph.length;
    int[] dist = new int[V];
    boolean[] visited = new boolean[V];

    for (int i = 0; i < V; i++) {
        dist[i] = Integer.MAX_VALUE;
    }

    dist[src] = 0;

    for (int i = 0; i < V - 1; i++) {
        int u = -1;

        for (int j = 0; j < V; j++) {
            if (!visited[j] && (u == -1 || dist[j] < dist[u])) {
                u = j;
            }
        }

        visited[u] = true;

        for (int v = 0; v < V; v++) {
            if (graph[u][v] != 0 && !visited[v]) {
                dist[v] = Math.min(dist[v], dist[u] + graph[u][v]);
            }
        }
    }

    System.out.println("Vertex \t\t Distance from Source");
    for (int i = 0; i < V; i++) {
        System.out.println(i + "\t\t\t" + dist[i]);
    }
}
Bellman-Ford算法实现
public void bellmanFord(int[][] graph, int src) {
    int V = graph.length;
    int[] dist = new int[V];

    for (int i = 0; i < V; i++) {
        dist[i] = Integer.MAX_VALUE;
    }

    dist[src] = 0;

    for (int i = 1; i <= V - 1; i++) {
        for (int u = 0; u < V; u++) {
            for (int v = 0; v < V; v++) {
                if (graph[u][v] != 0 && dist[u] != Integer.MAX_VALUE && dist[u] + graph[u][v] < dist[v]) {
                    dist[v] = dist[u] + graph[u][v];
                }
            }
        }
    }

    for (int u = 0; u < V; u++) {
        for (int v = 0; v < V; v++) {
            if (graph[u][v] != 0 && dist[u] != Integer.MAX_VALUE && dist[u] + graph[u][v] < dist[v]) {
                System.out.println("Graph contains negative weight cycle");
                return;
            }
        }
    }

    System.out.println("Vertex \t\t Distance from Source");
    for (int i = 0; i < V; i++) {
        System.out.println(i + "\t\t\t" + dist[i]);
    }
}
总结

最短路径算法是图论中一个经典问题,Dijkstra算法和Bellman-Ford算法是解决该问题的两种有效方法。其中,Dijkstra算法是一种贪心算法,可以处理无负权重的图,而Bellman-Ford算法是一种动态规划的方法,可以处理有负权重的图。无论是哪种算法,我们都需要对每个节点进行遍历,并记录每个节点到源节点的最短路径。在实际应用中,我们可以根据具体问题选取合适的算法来解决最短路径问题。