이런 그래프가 있다고 했을 때 최단 경로를 한다면 이렇게 구하자는거다
1. 모든 경로에 대한 가중치를 입력한다.
2. 이렇게 나온 가중치는 최단 경로가 아니다.
정점 3으로 가는건 2->3 보다 2->1->3이 최단경로가 된다.
3. 이제 각 정점에 대해 최단 경로를 갱신한다.
4. 갱신된 경로를 이용해 다시 경로를 갱신한다.
5. 결국 K번째 연산이 수행됐을 때 우리가 원하는 모든 정점을 거치는 최단 경로가 완성된다.
요컨대 우리가 알고싶은건 까지의 연산과 , 를 지키지 않고 그냥 대입하는데 어떻게 최단 경로가 구성되는가인데 굉장히 간단하다.
우리가 알고싶은 건 거리가 아닌 경로인데 이 경로를 어떻게 추적할까
기록용 배열을 따로 두고 최단 거리로부터 각 경로를 따라 이동하면 되는데
이는 와 가 있다면 그 사이의 모든 정점을 거치기만 한다면 경로를 추적할 수 있기때문이다.
알면서도 설명이 좀 어려운데 간단하게 설명되어 있는 링크가 있다.
바킹독 경로복원
public void floyd() {
long[][] spfArr = new long[graph.length][graph.length];
for (int i = 0; i < graph.length; i++) { // 수행 할 배열
System.arraycopy(graph[i], 0, spfArr[i], 0, spfArr.length);
}
for (int i = 0; i < spfArr.length; i++) { // 자기 자신으로 가는 길은 거리 0
spfArr[i][i] = 0;
}
for (int k = 0; k < spfArr.length; k++) { // 거치는 정점 K
for (int i = 0; i < spfArr.length; i++) { // 정점 K에 대해 모든 정점 순회
for (int j = 0; j < spfArr.length; j++) {
// 기존 거리와 정점을 거치는 거리 비교
spfArr[i][j] = Math.min(spfArr[i][j], (spfArr[i][k] + spfArr[k][j]));
}
}
for (long[] i : spfArr) {
System.out.println(Arrays.toString(i));
}
System.out.println();
}
}
출력
[0, 4, 1, 1, 2147483647]
[4, 0, 5, 5, 8]
[1, 5, 0, 2, 15]
[1, 5, 2, 0, 6]
[2147483647, 8, 15, 6, 0]
[0, 4, 1, 1, 12]
[4, 0, 5, 5, 8]
[1, 5, 0, 2, 13]
[1, 5, 2, 0, 6]
[12, 8, 13, 6, 0]
[0, 4, 1, 1, 12]
[4, 0, 5, 5, 8]
[1, 5, 0, 2, 13]
[1, 5, 2, 0, 6]
[12, 8, 13, 6, 0]
[0, 4, 1, 1, 7]
[4, 0, 5, 5, 8]
[1, 5, 0, 2, 8]
[1, 5, 2, 0, 6]
[7, 8, 8, 6, 0]
[0, 4, 1, 1, 7]
[4, 0, 5, 5, 8]
[1, 5, 0, 2, 8]
[1, 5, 2, 0, 6]
[7, 8, 8, 6, 0]