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

+ Recent posts