여전히 헷갈리는 다익스트라..
2024. 4. 16. 14:23ㆍ카테고리 없음
package com.example.demo;
import java.io.*;
import java.util.*;
/*
우선 각 테스트에 컴퓨터N 의존성M 해킹 컴퓨터C가 주어지는데
의존성에 엮인 컴퓨터는 대상이 해킹되면 S초 후에 자기도 전염되서 감염된다.
문제는 마지막 컴퓨터가 언제 감염이 되는지 묻는것이다.
*/
public class Main {
static final int INF = Integer.MAX_VALUE;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int T = Integer.parseInt(br.readLine());
while (T-- > 0) {
st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int C = Integer.parseInt(st.nextToken());
Map<Integer, List<int[]>> graph = new HashMap<>();
int[] distance = new int[N + 1];
Arrays.fill(distance, INF);
for (int i = 1; i <= N; i++) {
graph.put(i, new ArrayList<>());
}
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int s = Integer.parseInt(st.nextToken());
graph.get(b).add(new int[]{a, s});
}
dijkstra(graph, distance, C);
int count = 0;
int maxTime = 0;
for (int i = 1; i <= N; i++) {
if (distance[i] != INF) {
count++;
maxTime = Math.max(maxTime, distance[i]);
}
}
System.out.println(count + " " + maxTime);
}
}
static void dijkstra(Map<Integer, List<int[]>> graph, int[] distance, int start) {
//거리가 짧은 노드부터 시작
PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(o -> o[1]));
pq.offer(new int[]{start, 0});
distance[start] = 0;
while (!pq.isEmpty()) {
int[] node = pq.poll();
int now = node[0];
int dist = node[1];
//최단 거리가 이미 갱신된 경우 그냥 넘김
if (distance[now] < dist) continue;
//현재 노드의 인접한 노드들을 순회하면서 최단 거리를 갱신
for (int[] next : graph.get(now)) {
int nextNode = next[0];
int cost = dist + next[1];
if (cost < distance[nextNode]) {
distance[nextNode] = cost;
pq.offer(new int[]{nextNode, cost});
}
}
}
}
}
다익스트라 알고리즘은 이 문제에서 최단 경로를 찾기 위해 사용했는데 그래프에서 각 노드 간의 최단 거리를 계산하여 해킹된 컴퓨터로부터의 거리를 찾기 위해 썼다.
하나의 시작 노드로부터 다른 모든 노드까지의 최단 거리를 찾는다. 각 노드까지의 최단 거리를 저장하는 배열(여기서는 distance 배열)를 관리하면서 우선순위 큐를 사용하여 최단 거리를 갱신한다.
최초에는 시작 노드랑 거리0으로 시작해서 pq에서 노드를 하나씩 poll해주며 빌때까지 반복해주는데 이 과정에서 최단거리가 기존 최단거리보다 적다면 pq에 넣어줘서 다음 반복에 사용한다.
다익스트라는 그래프에서 출발지부터 모든 노드까지의 최단 거리를 구하는데 쓰이는 것이기에 bfs랑 상당히 유사한 점이많아(큐도 쓰고) 어떤걸 써야하는지 구분하는게 참 어려운것같다(파악하는게 실제 코테에서도 오래걸린다고 한다.)