[백준] 1238번 - 파티 (Gold 3)
업데이트:
문제 링크
문제 설명
N($\leq$ 1,000)개의 마을과 이들 사이를 잇는 M($\leq$ 10,000)개의 단방향 도로들이 있다.
각 도로의 출발지, 도착지, 지나는데 걸리는 시간이 주어져 있다.
각 마을에서 주어진 마을 X까지 갔다가 다시 돌아가는데 걸리는 시간 중 최댓값을 구하시오.
정답 코드 및 설명
마을 X에서 각 마을로 돌아가는 시간은 다익스트라를 통해 쉽게 구할 수 있다.
각 마을에서 X로 가는데 걸리는 시간은 모든 도로를 역방향으로 두고 X에서 시작하는 다익스트라를 통해 구할 수 있다.
만일 모든 (출발지, 도착지) 쌍에 대해 소요 시간을 구함으로써 접근한다면 플로이드-워셜 알고리즘을 사용하게 될텐데, 이렇게 하면 $O(N^3)$이 소요되므로 시간 초과가 발생한다.
하지만 위와 같이 푼다면 모든 도로를 역방향으로 돌리는 시간 $O(M)$과 다익스트라를 두 번 돌리는 시간 $O(M \log M)$만 필요하므로, 전체 시간 복잡도가 $O(M \log M)$이 된다.
시간 복잡도를 정확히 계산하려면 마지막에 왕복 거리의 최댓값을 구하는 과정에 필요한 $O(N)$도 더해주어야하는데, 어차피 $O(N^3)$ 내지는 $O(M \log M)$에 비해 무시할만큼 작은 값이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class BOJ1238 {
static final int INF = 2_000_000;
int n, x;
int[][] roads;
void input() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
x = Integer.parseInt(st.nextToken()) - 1;
setRoads(m, br);
}
void setRoads(int m, BufferedReader br) throws IOException {
roads = new int[n][n];
StringTokenizer st;
int start, end;
while (m-- > 0) {
st = new StringTokenizer(br.readLine());
start = Integer.parseInt(st.nextToken()) - 1;
end = Integer.parseInt(st.nextToken()) - 1;
roads[start][end] = Integer.parseInt(st.nextToken());
}
}
int[][] reverse(int[][] roads) {
int[][] reverse = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
reverse[i][j] = roads[j][i];
}
}
return reverse;
}
int[] Dijkstra(int start, int[][] roads) {
class City {
final int cityNo;
final int minTime;
public City(int cityNo, int minTime) {
this.cityNo = cityNo;
this.minTime = minTime;
}
}
int[] minTime = new int[n];
Arrays.fill(minTime, INF);
minTime[start] = 0;
PriorityQueue<City> pq = new PriorityQueue<>(Comparator.comparingInt(c -> c.minTime));
pq.add(new City(start, 0));
while (!pq.isEmpty()) {
City currCity = pq.poll();
if (minTime[currCity.cityNo] < currCity.minTime) continue;
for (int i = 0; i < n; i++) {
if (roads[currCity.cityNo][i] == 0) continue;
if (minTime[currCity.cityNo] + roads[currCity.cityNo][i] < minTime[i]) {
minTime[i] = minTime[currCity.cityNo] + roads[currCity.cityNo][i];
pq.add(new City(i, minTime[i]));
}
}
}
return minTime;
}
int max(int start) {
int[] goingTime = Dijkstra(start, roads);
int[] returningTime = Dijkstra(start, reverse(roads));
int max = 0;
for (int i = 0; i < n; i++) {
if (max < goingTime[i] + returningTime[i])
max = goingTime[i] + returningTime[i];
}
return max;
}
void solution() throws IOException {
input();
System.out.println(max(x));
}
public static void main(String[] args) throws IOException {
new BOJ1238().solution();
}
}
댓글남기기