




사용한 알고리즘 : 프로이드 - 워셜 알고리즘
해당 문제는 최단경로를 찾는것이기 때문에
다익스트라 알고리즘 과 프로이드- 워셜 알고리즘 중에
하나를 선택해야 했다.
기본적으로 다익스트라 알고리즘이 단일 시작점에서 다른 노드까지의 최단 경로를 찾는데 매우 효율 적이다.
다익스트라 알고리즘은 우선순위 큐를 사용하면, 시간복잡도는
로,
프로이드 - 워셜 알고리즘의 의 시간복잡도 보다 빠르기 때문이다.
E는 간선의 수, V는 노드의 수
하지만 해당 문제는 합승이 가능한 모든 지점을 거쳐 각각의 목적지 까지의 최단거리를 구하는 것 이었기 때문에 모든 노드들간의 거리를 저장할 필요가 있었다.
저장한 모든 노드들간의 거리를 확인해 최단거리를 리턴하는것이 이번 문제의 목표.
해당 그림처럼 연결이 되지 않은 부분(간선이 없는 부분)은 무한대로 설정된다.
final static int INF = 9999999;
static int[][] dist;
public static void floydWarshall(int n, int[][] fares) {
dist = new int[n + 1][n + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i !=j) {
dist[i][j] = INF;
}
}
}
for (int[] fare : fares) {
dist[fare[0]][fare[1]] = fare[2];
dist[fare[1]][fare[0]] = fare[2];
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (dist[i][k] != INF && dist[k][j] != INF) {
dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]);
}
}
}
}
}
floydWarshall(n, fares);
int min = INF;
경로가 존재한다면, 최소 요금 갱신for (int i = 1; i <= n; i++) {
if (dist[s][i] != INF && dist[i][a] != INF && dist[i][b] != INF) {
min = Math.min(min, dist[s][i] + dist[i][a] + dist[i][b]);
}
}
거리 배열 초기화
| node | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| 1 | 0 | INF | INF | INF | INF | INF |
| 2 | INF | 0 | INF | INF | INF | INF |
| 3 | INF | INF | 0 | INF | INF | INF |
| 4 | INF | INF | INF | 0 | INF | INF |
| 5 | INF | INF | INF | INF | 0 | INF |
| 6 | INF | INF | INF | INF | INF | 0 |
주어진 간선 정보로 거리배열 초기화
| node | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| 1 | 0 | INF | INF | INF | INF | 25 |
| 2 | INF | 0 | 22 | 66 | INF | INF |
| 3 | 41 | INF | 0 | INF | 24 | INF |
| 4 | 10 | INF | INF | 0 | INF | 50 |
| 5 | 24 | INF | INF | INF | 0 | 2 |
| 6 | INF | INF | INF | INF | INF | 0 |
양방향 이므로 반대 거리도 초기화
| node | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| 1 | 0 | INF | 41 | 10 | 24 | 25 |
| 2 | INF | 0 | 22 | 66 | INF | INF |
| 3 | 41 | 22 | 0 | INF | 24 | INF |
| 4 | 10 | 66 | INF | 0 | INF | 50 |
| 5 | 24 | INF | 24 | INF | 0 | 2 |
| 6 | 25 | INF | INF | 50 | 2 | 0 |
프로이드 - 워셜 알고리즘으로 최단거리 갱신
| node | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| 1 | 0 | 63 | 41 | 10 | 24 | 25 |
| 2 | 63 | 0 | 22 | 66 | 46 | 101 |
| 3 | 41 | 22 | 0 | 51 | 24 | 26 |
| 4 | 10 | 66 | 51 | 0 | 34 | 35 |
| 5 | 24 | 46 | 24 | 34 | 0 | 2 |
| 6 | 25 | 101 | 26 | 35 | 2 | 0 |
class Solution {
final static int INF = 9999999;
static int[][] dist;
public static void floydWarshall(int n, int[][] fares) {
dist = new int[n + 1][n + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i !=j) {
dist[i][j] = INF;
}
}
}
for (int[] fare : fares) {
dist[fare[0]][fare[1]] = fare[2];
dist[fare[1]][fare[0]] = fare[2];
}
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (dist[i][k] != INF && dist[k][j] != INF) {
dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]);
}
}
}
}
}
public int solution(int n, int s, int a, int b, int[][] fares) {
floydWarshall(n, fares);
int min = INF;
for (int i = 1; i <= n; i++) {
if (dist[s][i] != INF && dist[i][a] != INF && dist[i][b] != INF) {
min = Math.min(min, dist[s][i] + dist[i][a] + dist[i][b]);
}
}
return min;
}
public static void main(String[] args) {
Solution sol = new Solution();
int n = 6;
int s = 4;
int a = 6;
int b = 2;
int[][] fares = {{4, 1, 10}, {3, 5, 24}, {5, 6, 2}, {3, 1, 41}, {5, 1, 24}, {4, 6, 50}, {2, 4, 66}, {2, 3, 22}, {1, 6, 25}};
System.out.println(sol.solution(n, s, a, b, fares));
}
}

dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])