[アルゴリズム]最短パス


📌 マルチアウトレット最短パスアルゴリズム
  • ある点から別の点への最短経路が必要である場合、
  • が必要である.
  • 図には複数のノードがあります.
    1つのアルゴリズム
  • は、1つのノードから別のノードへの最短経路を解く.
  • 階調アルゴリズムに分類
    (最小コストのノードを毎回繰り返し選択するため、ステップごとに最短距離のノードを繰り返し選択する)
  • 前提条件
    接続
  • グラフィック
  • 幹線無方向
  • 幹線の重量は負数X
  • である.
    過程を見てみましょう.
    1.出発ノードの設定(start)
    2.最短距離テーブルの初期化(distance)
    3.アクセスされていないノードで、最短距離のノードを選択
    4.このノードを介して他のノードへのコストを計算し、最短距離テーブルを更新する(グリーンディ)
    5.3-4繰り返し
    単純なマルチアウトプットアルゴリズム
    時間複雑度O(V^2)
    import sys
    input = sys.stdin.readline
    INF = int(1e9) # 무한을 의미(10억)
    
    # 노드의 개수, 간선의 개수 입력 받기
    n, e = map(int, input().split())
    # 시작 노드 번호 입력 받기
    start = int(input())
    # 각 노드에 연결되어 있는 노드에 대한 정보를 담는 리스트 담기
    graph = [[] for i in range(n + 1)] # n + 1 !!!
    # 방문한 적이 있는지 체크하는 리스트
    visited = [False] * (n + 1)
    # 최단 거리 테이블
    # 계속 갱신할 리스트
    distance = [INF] * (n + 1)
    
    # 모든 간선 정보 입력 받기
    for _ in range(e): # 간선의 개수만큼 입력 받기
      a, b, c = map(int, input().split()) # a -> b로 가는 가중치 c
      graph[a].append((b, c)) # 튜플
    
    # 방문하지 않은 노드 중, 가장 최단 거리가 짧은 노드의 번호 반환
    # distance 로 비교
    def get_smallest_node():
      min_value = INF
      index = 0 # 가장 짧은 노드 인덱스
      for i in range(1, n + 1): # 1 ~ n 노드에서 찾기
        if distance[i] > min_value and not visited[i]:
          min_value = distance[i]
          index = i
      return index
    
    def dijkstra(start):
      visited[start] = True
      distance[start] = 0
      for j in graph[start]:
        distance[j[0]] = j[1]
      # 시작 노드를 제외한 전체 (n - 1)개의 노드에 대해 반복
      for i in range(n - 1):
        # 현재 최단 거리가 가장 짧은 노드를 꺼내 방문 처리
        now = get_smallest_node() # 현재 노드 설정
        visited[now] = True
        # 현재 노드와 연결된 다른 노드 확인
        for j in graph[now]:
          # 최단 경로 갱신하자
          cost = distance[now] + j[1]
          # 현재 노드 + 가중치 가 더 짧은 경우
          if cost < distance[j[0]]:
            distance[j[0]] = cost # 갱신
    
    dijkstra(start)
    
    # 모든 노드로 가기 위한 최단 거리 출력
    for i in range(1, n + 1):
      # 도달할 수 없는 경우 INF 출력
      if distance[i] == INF:
        print('*')
      else:
        print(distance[i])
    改良されたマルチアウトプットアルゴリズム
    時間複雑度O(EGV)
    heapqライブラリ-hipデータ構造の使用
    heapqライブラリはtupleを要素として入力し、tupleの最初の要素に基づいて優先順位キューを構成します.
    ->(距離、ノード番号)凡例データを順番に整理し、優先順位キューに入れ、距離順に並べ替える
    import heapq # 우선순위큐
    import sys
    
    input = sys.stdin.readline
    INF = int(1e9)
    
    n, e = map(int, input().split()) # 노드, 간선의 개수
    start = int(input()) # 시작점
    
    graph = [[] for i in range(n + 1)] #####
    distance = [INF] * (n + 1)
    
    for _ in range(e):
      a, b, c = map(int, input().split())
      # graph[a][b] = c # 오류
      graph[a].append((b, c)) # 튜플
    
    def dijkstra(start):
      q = []
      # 시작 노드로 가기 위한 최단 경로는 0으로 설정해서, 큐에 삽입
      heapq.heappush(q, (0, start)) # (0, start) = (가중치, 노드)
      distance[start] = 0
      while q: # 큐가 비어있지 않으면 반복
        dist, now = heapq.heappop(q)
        if distance[now] < dist: # 이미 처리된 노드이면 무시
         continue
        # 현재 노드와 연결된 다른 인접한 노드 확인(갱신위함)
        for i in graph[now]:
          cost = i[1] + dist
          if cost < distance[i[0]]:
            distance[i[0]] = cost # 갱신
            heapq.heappush(q, (cost, i[0])) # 갱신하면 push
    
    dijkstra(start)
    
    for i in range(1, n + 1):
      if distance[i] == INF:
        print("*", end = ' ')
      else:
        print(distance[i], end = ' ')
    📌 りゅうすいアルゴリズム

  • すべてのポイントから他のすべてのポイントへの最短パスが必要です.

  • 核心的な考えを理解しましょう.

  • マルチアウトアルゴリズムは、各ステップで最短距離のノードを繰り返し選択します.
    ノードを通過するパスを決定し、最短距離テーブルを更新するように操作します.
    flowersalアルゴリズムも、各ステップの「通過ノード」に基づいてアルゴリズムを実行します.
    アクセスしないノードのたびに、最短距離のノードを探す必要はありません.

  • ノード数がNの場合、アルゴリズム上でN個のステップが実行され、各ステップはO(N^2)の演算により
    現在のノードを通るすべてのパスを考慮👉 総時間複雑度:O(N^3)

  • このアルゴリズムは2 Dリストに最短距離情報(distance)を格納する.
    (マルチファンクションという名前の1次元)

  • 動的プログラミング:ノード数がN個の場合、手順をN回繰り返し、点火式に従って2 Dリストを更新します.

  • 各ステップは、対応するノードが通過した場合を考慮します.
    ex)ノードが1番の場合:A->1番のノード->Bのコストを確定した後、最短距離を更新する
  • てんかしき
    Dab = min(Dab, Dak + Dkb)
    三重複文
    for k in range(n):
       for i in range(n):
          for j in range(n):
             distance[i][j] = min(distance[i][j], distance[i][k] + distance[k][j]
    ソースコード
    INF = int(1e9) # 무한을 의미하는 값으로 10억 
    
    # 노드, 간선의 개수
    n = int(input())
    m = int(input())
    
    # 2차원 리스트(그래프 표현)을 만들고, 무한으로 초기화
    graph = [[INF] * (n + 1) for _ in range(n + 1)] # 2차원으로 가능
    # graph = [[] for i in range(n + 1)] -> 튜플이고
    
    # 자기 자신의 비용은 0으로 
    for a in range(1, n + 1):
      for b in range(1, n + 1):
        if a == b:
          graph[a][b] = 0
    
    # 간선의 정보 입력 받기
    for _ in range(m):
        # A에서 B로 가는 비용 C
        a, b, c = map(int, input().split())
        graph[a][b] = c 
        # graph = [[] for i in range(n + 1)] 
        # 만약 이런 graph를 선언했으면 오류 index
    
    # 점화식에 따라 플로이드 알고리즘 수행
    #  O(N^3)
    for k in range(1, n + 1):
      for a in range(1, n + 1):
        for b in range(1, n + 1):
          graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b])
    
    for a in range(1, n + 1):
      for b in range(1, n + 1):
        if graph[a][b] == INF:
          print('*', end = ' ')
        else:
          print(graph[a][b])
      print()