import java.util.*;
// 그래프의 노드를 표현하는 클래스
// 이 노드는 특정 노드(targetNode)까지의 거리(distance) 정보를 담고 있음
// 우선순위 큐에서 거리가 짧은 순으로 정렬하기 위해 Comparable 인터페이스를 구현
class Node implements Comparable<Node> {
int targetNode;
int distance;
public Node(int targetNode, int distance) {
this.targetNode = targetNode;
this.distance = distance;
}
// 거리가 짧은 것이 높은 우선순위를 가지도록 compareTo 메서드를 오버라이드
@Override
public int compareTo(Node other) {
return this.distance - other.distance;
}
}
public class DijkstraTemplate {
// 무한대를 의미하는 값 (문제의 최대 간선 가중치 합보다 큰 값으로 설정)
private static final int INF = Integer.MAX_VALUE;
// 그래프 정보를 담을 인접 리스트
// 각 ArrayList는 특정 노드와 연결된 다른 노드들의 정보를 담고 있음
private static ArrayList<ArrayList<Node>> graph;
// 최단 거리 테이블
private static int[] shortestPath;
public static void main(String[] args) {
// --- 입력 예시 (문제에 맞게 수정) ---
int numNodes = 6; // 노드 개수
int numEdges = 11; // 간선 개수
int startNode = 1; // 시작 노드 번호
// 그래프 및 최단 거리 테이블 초기화
graph = new ArrayList<>();
for (int i = 0; i <= numNodes; i++) {
graph.add(new ArrayList<>());
}
shortestPath = new int[numNodes + 1];
Arrays.fill(shortestPath, INF); // 모든 거리를 무한대로 초기화
// 간선 정보 입력 (시작 노드, 끝 노드, 가중치)
// 예시: 1번 노드에서 2번 노드로 가는 비용이 2
// graph.get(1).add(new Node(2, 2));
int[][] edges = {
{1, 2, 2}, {1, 3, 5}, {1, 4, 1},
{2, 3, 3}, {2, 4, 2},
{3, 2, 3}, {3, 6, 5},
{4, 3, 3}, {4, 5, 1},
{5, 3, 1}, {5, 6, 2}
};
for (int[] edge : edges) {
graph.get(edge[0]).add(new Node(edge[1], edge[2]));
}
// --- 입력 끝 ---
// 다익스트라 알고리즘 실행
dijkstra(startNode);
// 결과 출력
System.out.println("--- 최단 거리 결과 ---");
for (int i = 1; i <= numNodes; i++) {
if (shortestPath[i] == INF) {
System.out.println("노드 " + i + ": 도달할 수 없음");
} else {
System.out.println("노드 " + i + ": " + shortestPath[i]);
}
}
}
/**
* 다익스트라 알고리즘을 수행하는 함수
* @param start 시작 노드
*/
private static void dijkstra(int start) {
// 우선순위 큐 생성 (거리가 짧은 노드 순으로 자동 정렬)
PriorityQueue<Node> pq = new PriorityQueue<>();
// 1. 시작 노드 초기화
shortestPath[start] = 0;
pq.offer(new Node(start, 0)); // 큐에 시작 노드 추가 (자기 자신까지의 거리는 0)
// 2. 큐가 빌 때까지 반복
while (!pq.isEmpty()) {
// 현재 가장 거리가 짧은 노드 정보를 꺼냄
Node currentNode = pq.poll();
int dist = currentNode.distance;
int now = currentNode.targetNode;
// 이미 처리된 노드라면 무시
// (큐에 남아있는, 더 긴 경로로 도착한 경우를 건너뛰기 위함)
if (shortestPath[now] < dist) {
continue;
}
// 3. 현재 노드와 연결된 다른 인접 노드들을 확인
for (Node nextNode : graph.get(now)) {
int cost = shortestPath[now] + nextNode.distance; // 현재 노드를 거쳐 가는 비용
// 현재 노드를 거쳐 가는 것이 기존 최단 거리보다 더 짧다면
if (cost < shortestPath[nextNode.targetNode]) {
shortestPath[nextNode.targetNode] = cost; // 최단 거리 갱신
pq.offer(new Node(nextNode.targetNode, cost)); // 갱신된 정보를 큐에 추가
}
}
}
}
}
알고리즘 진행 순서
초기 설정
shortestPath배열을INF로 채웁니다.- 시작 노드의
shortestPath값을 0으로 설정합니다. - 우선순위 큐에 시작 노드
new Node(start, 0)을 넣습니다.
반복문 (while !pq.isEmpty())
- 우선순위 큐에서 가장 거리가 짧은 노드(
currentNode)를 꺼냅니다. - 꺼낸 노드의 거리가
shortestPath에 기록된 값보다 크다면, 이미 더 빠른 경로가 발견된 것이므로 무시하고 건너뜁니다(continue). (이 부분이 효율성을 높이는 핵심!) - 꺼낸 노드와 연결된 모든 인접 노드들을 순회합니다.
- 인접 노드 각각에 대해, 현재 노드를 거쳐 가는 것이 기존의 최단 거리보다 짧은지 확인합니다.
- “현재 노드까지의 최단 거리 + 인접 노드까지의 간선 가중치” < “기존에 알려진 인접 노드까지의 최단 거리”
- 만약 더 짧다면, 인접 노드의 최단 거리를 갱신하고, 갱신된 정보를 우선순위 큐에 새로 추가합니다.