📢 주어진 Graph에서 주어진 두 Node를 연결하는 가장 짧은 경로의 길이
최단 경로 문제를 해결 할 때 가장 먼저 주의해야 하는 부분이에요. 바로 가중치 값이 음수를 가지는지 확인해야 해요.
만일 음수 간선이 존재한다면 음수 사이클이 존재할 수 있고, 위의 그림처럼 음수 사이클이 존재한다면 최단 경로를 찾을 수 없어요.
📢 우선 순위 큐를 사용해 각 Node까지의 최단 경로들을 구하는 알고리즘
위의 그림을 보면서 설명할게요. s에서 출발하여 각 Node까지의 최단 거리를 구해볼거에요. 시작점에서 각 Node까지의 최단 거리를 나타내는 dist배열, 그리고 각 Node를 방문하면서 시작점에서 해당 Node까지 가는데 걸리는 길이를 cost라고 할게요.
아래 예제를 통해 알고리즘 코드 올리도록 할게요.
백준 1753 - 최단경로
백준 1753 - 해답
백준 1238 - 파티
백준 1238 - 해답
📢 각 정점까지 최단 거리의 상한을 적당히 예측한 뒤, 예측 값과 실제 최단 거리 사이의 오차를 반복적으로 줄여나가는 방식
초기에 우리가 아는 사실은 시작점 s에서 s까지의 거리는 0, 즉 upper[s] = 0 이라는 사실만 알아요. upper[s] = 0으로 초기화하고 나머지 값들은 아주 큰 수로 초기화 해요. 그 다음엔 아래의 특성들을 이용해 값을 찾아나가게 돼요.
dist[v] <= dist[u] + w(v, u) (dist[v]는 시작점에서 v까지의 최단 거리, w(v, u)는 v와 u사이의 거리)
upper[u] + w(u, v) < upper[v] 를 이용해 upper[v]를 감소 시키는 과정
upper[u] >= dist[u] 입니다. upper배열은 해당 지점까지의 최단거리에 점점 가까워지는 배열이고 dist배열은 해당 지점까지의 최단거리 값을 가지고 있는 배열이니까요. 고로, upper[u] 값이 줄어든다면 upper[v] 값을 upper[u] + w(u, v)로 바꿔도 상관어요. 이 과정을 완화(Relax)라고 해요.
시작점 s에서 d까지의 최단 거리를 가는 경로가 위의 그림과 같다고 가정할 때 아래의 순서를 가져요.
1. upper[s] = 0이에요.
2, 모든 Edge들을 순회하면서 한 번씩 완화를 시도하면 (s, a)도 하나의 Edge이므로 완화가 되었어요.
3. 최단 거리 특성을 생각해보면 upper[a] <= upper[s] + w(s, a)가 성립해요.
4. 이때, upper[s] = 0이고 w(s, a)는 시작점에서 a까지의 최단거리를 나타내니까 upper[a] = w(s, a)가 성립 해요. 즉, upper[a]는 최단거리로 되었어요.
5. 이를 반복하게 되면 b, c, d가 최단 경로가 된다는 것을 알 수 있어요.
6. 모든 Edge을 한 번씩 완화하는 과정을 E - 1번 반복하면 최단 경로를 얻을 수 있어요.
아까 위에서 모든 Edge를 한 번씩 완화하는 과정을 E - 1번 반복하면 된다고 했는데 이후에 한 번더 반복을 하면 돼요. 음수가 존재한다면 한 번 더 완화 하는 과정에서 더 작은 값이 존재하게 되므로 완화에 성공하게 돼요.
백준 11657 - 타임머신
백준 11657 - 해답
백준 1865 - 웜홀
백준 1865 - 해답
📢 음수 사이클이 존재하지 않을 때 모든 Node 간의 최단 경로를 구하는 알고리즘
위의 그림에서 u에서 v로 가는 경로가 있다고 가정해요. 이때 그 경로는 u와 v는 당연히 지나고 이를 제외한 다른 지점(B)을 또 지날 수도 있어요. 이렇게 경로가 거쳐가는 다른 지점을 경유점이라고 해요.
집합 S에 임의의 Node들이 포함되어 있을 때, S에 포함된 Node만 사용하여 u에서 v로 가는 최단 경로가 존재한다고 가정해요. S 중에 아무 Node를 골라 x라고 한다면 최단 경로는 x를 경유하거나 안할 수 있어요. 이때 각각을 우리는 아래와 같이 표현할 수 있어요.
이를 점화식으로 나타내면 아래와 같이 표현 할 수 있어요.
(여기서 Ck(u,v)는 0번 Node부터 k번 Node까지만을 경유점으로 썼을 때 u에서 v까지의 최단 거리를 뜻해요.)
단순히 위의 생각을 이용해서 코드를 구현하면 메모리가 부족해요. 그래서 실제로 알고리즘을 구현할 때는 DP를 사용해요. 시간 복잡도는 O()이에요.
백준 11403 - 경로 찾기
백준 11403 - 해답
백준 11404 - 플로이드
백준 11404 - 해답