import sys import heapq def dijkstra(start,end,flag=True): global INF,N distance = [INF]*N distance[start] = 0 node_list = [] heapq.heappush(node_list,(0,start)) while node_list: current_distance,node = heapq.heappop(node_list) if current_distance > distance[node]: continue for next_node in graph[node]: temp_distance = current_distance + graph[node][next_node] if distance[next_node] > temp_distance: distance[next_node] = temp_distance heapq.heappush(node_list,(temp_distance,next_node)) if flag and distance[end] != INF: stack = [(end,distance[end])] path_set = set() while stack: node,dis = stack.pop() for prev_node in parent[node]: if (prev_node,node) not in path_set: if distance[prev_node] + graph[prev_node][node] == dis: path_set.add((prev_node,node)) stack.append((prev_node,distance[prev_node])) for prev_node,next_node in path_set: del graph[prev_node][next_node] return distance[end] INF = float('inf') while True: N,M = map(int,sys.stdin.readline().split()) if not N+M: break S,D = map(int,sys.stdin.readline().split()) distance = [[0]*N for _ in range(N)] graph = [{} for _ in range(N)] parent = [[] for _ in range(N)] for _ in range(M): U,V,P = map(int,sys.stdin.readline().split()) graph[U][V] = P parent[V].append(U) min_distance = dijkstra(S,D) if min_distance == INF: print(-1) else: cu_distance = dijkstra(S,D,False) if cu_distance != min_distance: if cu_distance != INF: print(cu_distance) else: print(-1)
다익스트라 문제이다. 하지만 기존의 다익스트라와 달리, 최단경로를 찾아서 최적경로의 간선을 제거해줘야한다.
처음에, 최적경로 하나마다 삭제를 했더니, 최적경로의 간선은 다른 최적경로에서 사용을 할 수 있기 때문에 틀렸다고 나왔다.
두번째로는 시간초과의 늪에 많이 빠졌다. 처음에는 최적의 경로를 min_distance가 갱신될때마다 저장을 시켜놨더니
시간이 초과가 되었다.
그래서 다음과 같은 로직으로 최적의 경로쌍을 찾아다
도착지점의 distance의 값을 distance[end]라 하겠다.
distance[prev_node] + graph[prev_node][end] == distance[end]을 만족하는 prev_node는 prev_node에서 end node로 오는 최단경로임을 알수 있다.
이 (prev_node,end) 쌍을 지울 집합에 추가해주고, prev_node를 stack에 넣어준다.
이 과정을 반복하면, 끝점에서부터 최단경로로 오는 간선들을 전부 찾을 수 있다.
그리고 난뒤 해당 간선들을 지우는 과정을 하면 된다.
그리고 마지막으로 다익스트라를 한번 더 한뒤 결과에 맞게 출력해주면 된다.
다익스트라는 자주 쓰지 않던 알고리즘이라 푸는데 어려웠고, 기본적으로 다익스트라는 최단경로의 길이를 출력해주는 것이기 때문에, 최단경로의 경로를 이용하기 위해서 다익스트라 과정에서 나온 결과물을 이용해야한다는 점을 배웠다.
'알고리즘 > 백준' 카테고리의 다른 글
[BOJ/백준] 13023 ABCDE (0) | 2021.02.21 |
---|---|
[BOJ/백준] 2470 두 용액 (0) | 2021.02.20 |
[BOJ/백준] 5582 공통 부분 문자열 (0) | 2021.02.18 |
[BOJ/백준] 3020 개똥벌레 (0) | 2021.02.18 |
[BOJ/백준] 6593 상범 빌딩 (0) | 2021.02.17 |