728x90
문제
접근
- 가중치 O
- 방향 O
방향과 가중치가 있는 그래프이기 때문에 클래스를 활용한 인접리스트를 구현하였다.
그 후에 모든 학생이 위치한 노드로부터 X(파티 장소) 까지로의 최단 거리와 X(파티 장소) 에서 다시 자신이 위치한 마을로 돌아가는 최단 거리를 합친 것 중 가장 큰 값을 출력해야 하기 때문에 다익스트라 알고리즘을 사용하였다.
다익스트라 알고리즘은 그래프에서 하나의 시작 노드로부터 다른 모든 노드까지의 최단 경로를 구하는 알고리즘입니다. 이 알고리즘은 가중치가 있는 그래프에서 동작하며, 음의 가중치가 없는 그래프에 적합합니다.
다익스트라 알고리즘은 음의 가중치를 가진 그래프에서 사용할 수 없습니다. 음의 가중치가 있는 경우, 벨만-포드 알고리즘과 같은 다른 알고리즘을 사용해야 합니다.
문제 풀이
- 가중치 있는 인접 리스트 구현
- 이때, Node클래스에서 Comparable 인터페이스를 구현하고, compareTo 메서드를 오버라이딩하여 가중치(w)를 기준으로 오름차순 정렬을 하도록 변경했습니다. 이를 통해 우선순위 큐에서 올바르게 동작하도록 했습니다.
- 다익스트라 메서드 구현
- 각 노드에서 다른 노드까지의 최단 경로를 계산
- distFromX : 파티 장소 X에서 다른 모드 노드까지의 최단 경로를 계산
- 각 노드 i에서 X까지의 최단 경로를 계산한 후, 이 값과 disFromX[i]를 더해
- 파티에 갔다가 돌아오는 총 시간을 계산한다.
- 최대 시간 계산 : 모든 노드에서 파티를 갔다가 돌아오는 시간 중 최대 시간을 maxTime 에 저장하고 이를 출력한다.
시간 복잡도
O((V + E) log V)
전체 코드
package baekjoon_day01;
import java.io.*;
import java.util.*;
public class Party_1238 {
static class Node implements Comparable<Node> {
int v;
int w;
Node(int v, int w) {
this.v = v;
this.w = w;
}
@Override
public int compareTo(Node other) {
// 짧은 거리 선택.
return Integer.compare(this.w, other.w);
/*
Integer.compare 메서드는 두 정수를 비교하여 다음 값을 반환합니다:
음수 값: this.w가 other.w보다 작은 경우.
0: this.w와 other.w가 같은 경우.
양수 값: this.w가 other.w보다 큰 경우.
*/
}
}
static int N, M, X;
static List<Node>[] adj;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
X = Integer.parseInt(st.nextToken());
adj = new List[N + 1];
for (int i = 1; i <= N; i++) {
adj[i] = new ArrayList<>();
}
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int cur = Integer.parseInt(st.nextToken());
int nxt = Integer.parseInt(st.nextToken());
int weight = Integer.parseInt(st.nextToken());
adj[cur].add(new Node(nxt, weight));
}
int[] distFromX = dijkstra(X); // X로부터 모든 노드까지의 최단 거리 배열
int maxTime = 0;
for (int i = 1; i <= N; i++) {
if (i == X) continue;
int[] distToX = dijkstra(i); // 다른 노드에서부터 X 노드까지의 최단 거리.
int totalTime = distToX[X] + distFromX[i]; // i~X 로 가는 최단 거리 + X~i 로 가는 최단 거리
maxTime = Math.max(maxTime, totalTime);
}
System.out.println(maxTime);
}
private static int[] dijkstra(int start) {
PriorityQueue<Node> pq = new PriorityQueue<>();
pq.add(new Node(start, 0));
int[] dist = new int[N + 1]; // 각 노드에 대한 최단 거리 저장하는 배열 초기화
Arrays.fill(dist, Integer.MAX_VALUE); // 모든 노드까지의 거리를 무한대로 설정
dist[start] = 0;
while (!pq.isEmpty()) {
Node curNode = pq.poll(); // 우선순위 큐에서 가장 작은 가중치를 가진 노드를 꺼낸다.
int cur = curNode.v;
for (Node neighbor : adj[cur]) { // 현재 노드와 연결된 모든 이웃 노드를 탐색
if (dist[neighbor.v] > dist[cur] + neighbor.w) { // 현재 발견된 경로가 기존에 알고 있던 경로보다 더 짧은지 확인
dist[neighbor.v] = dist[cur] + neighbor.w; // 발견 시 최단 경로 업데이트
pq.add(new Node(neighbor.v, dist[neighbor.v])); // 경로가 업데이트된 이웃 노드를 우선순위 큐에 추가한다.
// 이후 큐가 다시 정렬되어 다음 반복에서는 최단 경로를 가진 노드를 다시 탐색한다.
}
}
}
return dist; // start노드로부터 다른 모든 노드까지의 최단 경로가 저장된 dist 배열을 반환한다.
// e.g. dist[i]에 start노드에서 i노드까지의 최단 경로가 저장된다.
}
}
728x90
반응형
'Study > Algorithm' 카테고리의 다른 글
[백준 11725] 트리의 부모 찾기 (0) | 2024.08.30 |
---|---|
[백준 14502] 연구소 (0) | 2024.08.27 |
[백준 1167] 트리의 지름 (0) | 2024.08.23 |
[백준 16953] A->B (0) | 2024.08.22 |
[백준 11660] 구간 합 구하기 5 (0) | 2024.08.21 |