📌  相关文章
📜  有向图和加权图中两个节点之间的简单路径的最小成本(1)

📅  最后修改于: 2023-12-03 14:55:23.893000             🧑  作者: Mango

有向图和加权图中两个节点之间的简单路径的最小成本

在有向图和加权图中,每个节点都可以与其他节点连接。两个节点之间的路径可以是简单路径,即不重复经过节点的路径。在此背景下,需要找出两个节点之间的最小成本的简单路径。

解法
Dijkstra算法

Dijkstra算法是解决带权有向图或者无向图的单源最短路径问题的一种算法,该算法的时间复杂度为$O((E+V)logV)$,其中E为边数,V为节点数。Dijkstra算法的主要思想是从某个节点出发,按照“距离”从小到大的顺序,逐渐扩展覆盖面。在扩展的过程中,利用一个数组(dis[])来记录源点到各个点的最短距离。

具体步骤如下:

  1. 初始时,源点到自己的距离为0,源点到其他节点的距离为无穷大(dis[i]=INF)。
  2. 将源点加入已确定最短路径的节点集合中。
  3. 对于源点能直接到达的节点,更新其距离。如源点到节点$u$的距离为$d$,对dis[u]进行更新:如果$d+dis[s][u] < dis[u]$,则更新dis[u]。
  4. 从还未被确定最短路径的节点中选择距离最小的节点,加入已确定最短路径的节点集合中。
  5. 重复步骤3和4,直到已确定最短路径的节点集合包含所有节点或者剩余的节点都不可达。

用Dijkstra算法来解决本题,可以找到两个节点之间的最短路径。

Floyd算法

Floyd算法是解决有权图中多源点之间的最短路的一种算法,该算法的时间复杂度为$O(V^3)$,其中V为节点数。Floyd算法的主要思想是依据中转点来逐步扩展,最终得到各个点之间的最短路径。

具体步骤如下:

  1. 初始时,若从i到j有直接的路径(即(i,j)边存在),则dis[i][j]为边的权值;否则dis[i][j]=INF。
  2. 对于每一对(i,j,k),如果dis[i][j] > dis[i][k] + dis[k][j],就用dis[i][k] + dis[k][j]来更新dis[i][j]。

用Floyd算法来解决本题,可以找到两个节点之间的最短路径。

代码实现
Dijkstra算法的Python实现
import heapq

def dijkstra(graph: List[List[Tuple[int, int]]], start: int, end: int) -> int:
    n = len(graph)
    dist = [float('inf')] * n
    dist[start] = 0
    visited = [False] * n
    pq = [(0, start)]  # 存放每个节点和其当前的最短距离

    while pq:
        _, u = heapq.heappop(pq)
        if visited[u]:
            continue
        visited[u] = True
        for v, w in graph[u]:
            if not visited[v] and dist[v] > dist[u] + w:
                dist[v] = dist[u] + w
                heapq.heappush(pq, (dist[v], v))

    return dist[end] if dist[end] < float('inf') else -1
Floyd算法的Python实现
def floyd(graph: List[List[int]]) -> List[List[int]]:
    n = len(graph)
    for k in range(n):
        for i in range(n):
            for j in range(n):
                graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j])
    return graph

以上就是在有向图和加权图中找两个节点之间的简单路径的最小成本的解法和代码实现。