0. ๊ตฌํ ์ค๋ช ์ ์์...
๋ณธ ํฌ์คํ ์ 'JAVA๋ฅผ ํ์ฉํด ๋ค์ต์คํธ๋ผ ๊ตฌํ์ ์ด๋ป๊ฒ ํ๋๊ฐ?'์ ๋ํด์ ๋ฐ๋ก ๋ค๋ฃฐ ์์ ์ด๋ค. ํน์ ์ด๋ก ๊ณต๋ถ๊ฐ ํ์ํ์ ๋ถ๋ค์ ๋ค์ต์คํธ๋ผ ๊ฐ๋ ์ ๋ฆฌ ํฌ์คํธ๋ฅผ ํ๋ฒ ์ฝ๊ณ ์ค์๊ธธ ๋น๋ถ ๋๋ฆฐ๋ค.
1. ์์ฐจ ํ์
์๊ณ ๋ฆฌ์ฆ ์ด๋ก ๊ทธ๋๋ก ์ฝ๋๋ก ์ฎ๊ธด ๊ตฌํ ๋ฐฉ๋ฒ์ด๋ค.
- 0๏ธโฃ ์์์ ์์์ ์ต๋จ ๊ฑฐ๋ฆฌ ๋ฐฐ์ด (dist) ๋ง๋ค๊ณ
INF
๋ก ์ด๊ธฐํ - 1๏ธโฃ ํ ์์ ์์ ๋ฐฉ๋ฌธํ์ง ์์ ๋ ธ๋ ์ค ์ต์ ๋น์ฉ์ผ๋ก ๋ฐฉ๋ฌธํ ์ ์๋ ๋ ธ๋(์ดํ A) ๋ฐฉ๋ฌธ
- 2๏ธโฃ ํด๋น ๋
ธ๋์ ์ธ์ ํ ๋
ธ๋(์ดํ B)๋ฅผ ํ์ฉํด dist ๋ฐฐ์ด์ ์ต์ ํ ํ๋ค.
- 2๏ธโฃ-1)
dist[B]
>dist[A] + A โ B ๊ฐ์ ๋น์ฉ
์ผ ์ dist ๋ฐฐ์ด ์ต์ ํ
- 2๏ธโฃ-1)
- 3๏ธโฃ ๋ชจ๋ ๋ ธ๋๋ฅผ ๋ฐฉ๋ฌธํ ๋๊น์ง 1๏ธโฃ,2๏ธโฃ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
(1) ์๊ฐ ๋ณต์ก๋ ๋ถ์
๋
ธ๋์ ๊ฐ์: N
. ๊ฐ์ ์ ๊ฐ์: E
๋ผ๊ณ ํ์.
- 1๏ธโฃ ๋งค๋ฒ dist ๋ฐฐ์ด์์ ๋ฐฉ๋ฌธํ์ง ์์ ๋
ธ๋ ์ค ์ต์๊ฐ์ ์ฐพ๋๋ค.
์ด N๋ฒ์ ๋ฐฉ๋ฌธ์ ํ ๊ฒ์ธ๋ฐ, ๊ทธ ๋๋ง๋ค ์ต์ ๋น์ฉ ๋ ธ๋๋ฅผ ์ฐพ๊ธฐ ์ํด, dist ๋ฐฐ์ด(N๊ฐ)๋ฅผ ์ํ ํด์ผํจ. : $O(N^{2})$ - 2๏ธโฃ N๋ฒ์ ๋ฐฉ๋ฌธ์ ํ๋ฉด ๊ฒฐ๊ตญ์ ๋ชจ๋ ๊ฐ์ ์ ๋ค ํ์ธํ๋ค๋ ์๋ฆฌ์ด๋ค. : $O(E)$
๋ฐ๋ผ์ ์ด $O(N^{2} + E)$์ ์๊ฐ๋ณต์ก๋๊ฐ ๋ ๋ค.
(2) ๊ตฌํ ์ฝ๋
import java.io.*;
import java.util.*;
public class ์์ฐจํ์_๋ค์ต์คํธ๋ผ {
static int [] dist = new int [N]; // N์ด ๋ณ์๊ฐ ์๋๋ผ ์์๋ผ ์น์
static boolean [] visited = new boolean [N];
static ArrayList<Node> [] lists;
public static void main(String[] args) throws IOException {
// ๋ฐฐ์ด์ ์์๊ฐ ์์๋
ธ๋, ๋ฐฐ์ด ์์ ๋์ด๋ ๊ฐ๋ค์ <๋์ฐฉ๋
ธ๋, ๊ฐ์ค์น> ๋ฌถ์
lists = new ArrayList [N+1];
for(int i = 1; i < N+1; i++){
lists[i] = new ArrayList<>();
}
// ๊ฐ ์
๋ ฅ ๋ฐ์์ ์ธ์ ๋ฆฌ์คํธ ์ฑ์ฐ๊ธฐ
// ...
Dijkstra(1);
}
public int ์ต๋จ๊ฑฐ๋ฆฌ๋
ธ๋์ฐพ๊ธฐ() {
int min_dist = Integer.MAX_VALUE;
int min_idx = -1;
for(int i = 0; i < N; i++){
if(visited[i]) continue;
if(dist[i] < min_dist){
min_dist = dist[i];
min_idx = i;
}
}
return min_idx;
}
// ์์๋
ธ๋๋ฅผ ์ธ์๋ก ๋ฐ์์, ํด๋น ๋
ธ๋๋ก๋ถํฐ ๋ชจ๋ ๋
ธ๋์ ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ dist์ ์
๋ ฅ
public void Dijkstra(int start) {
// 1. dist ๋ฐฐ์ด ์ด๊ธฐํ
Arrays.fill(dist, Integer.MAX_VALUE);
dist[start] = 0;
visited[start] = true;
// 2. ๋ณธ ๋ค์ต์คํธ๋ผ ์์ -> ๋ชจ๋ ๋
ธ๋ ๋ฐฉ๋ฌธํ ๋๊น์ง๋ง ๋ฐ๋ณตํ๋ฉด ๋จ.
for(int i = 0; i < N-1; i++){
int now_node = ์ต๋จ๊ฑฐ๋ฆฌ๋
ธ๋์ฐพ๊ธฐ();
visited[now_node] = true;
for(int j = 0; j < lists[now_node].size(); i++){
// ๋ง์ฝ ํ์ฌ๊น์ง j๋ก ๊ฐ๋ ์ต๋จ๊ฑฐ๋ฆฌ๋ณด๋ค now_node๋ฅผ ๊ฑฐ์ณ์ j๋ก ๊ฐ๋ ์ต๋จ๊ฑฐ๋ฆฌ๊ฐ ๋ ์งง์ ๊ฒฝ์ฐ ๊ฐฑ์
if(dist[j] > dist[now_node] + lists[now_node].get(j).w){
dist[j] = dist[now_node] + lists[now_node].get(j).w;
}
}
}
}
}
class Node {
int v; // ๋์ฐฉ ๋
ธ๋
int w; // ๋์ฐฉ ๋
ธ๋๊น์ง ๊ฐ๋ ๊ฐ์ ์ ๊ฐ์ค์น
public Node(int v, int w) {
this.v = v;
this.w = w;
}
}
2. ์ฐ์ ์์ ํ ํ์ฉ
dist ๋ฐฐ์ด์ ์ผ์ผํ ๋งค๋ฒ ํ์ธํ์ฌ ์ต์ ๋น์ฉ ๋
ธ๋ ์ฐพ๊ธฐ
โ ์ฐ์ ์์ ํ๋ก ๋ฐฉ๋ฌธ ์์ ์ธ ๋
ธ๋๋ฅผ dist๊ฐ ์์ ์์ผ๋ก ์ ๋ ฌ, ํ์ front ๋
ธ๋๋ฅผ ๋ฝ์์ ์ฌ์ฉ
์ผ๋ก ๋ฐ๊พธ๋ ๊ฒ์ด๋ค.
- 0๏ธโฃ
์ ์ ๋ฒํธ, ๋น์ dist[์ ์ ๋ฒํธ]๋ฅผ ๊ฐ์ง๋ ๊ฐ์ฒด
,dist ๋ฐฐ์ด
๊ณผPriority Queue
(์ฝ์ ํ ๋ ธ๋์ dist๊ฐ ์์ ์์ผ๋ก ์ ๋ ฌ)๋ฅผ ์์ฑํ๋ค. ์์์ ์ PQ์ ๋ฃ๋๋ค. - 1๏ธโฃ Priority Queue๊ฐ ๋น ๋๊น์ง ์ดํ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
- 2๏ธโฃ PQ์ front ๋ ธ๋ (์ดํ A)๋ฅผ ๋บด๋ธ๋ค.
- 3๏ธโฃ
A.dist(์ฝ์ ๋น์์ ์ต์ ๋น์ฉ)
!=dist[A]
์ด๋ฉด 2๏ธโฃ์ผ๋ก ๋์๊ฐ๋ค. - 4๏ธโฃ ํด๋น ๋
ธ๋์ ์ธ์ ํ ๋
ธ๋(์ดํ B)๋ฅผ ํ์ฉํด dist ๋ฐฐ์ด์ ์ต์ ํ ํ๋ค.
- 4๏ธโฃ-1)
dist[B]
>dist[A] + A โ B ๊ฐ์ ๋น์ฉ
์ผ ์ dist ๋ฐฐ์ด ์ต์ ํ
- 4๏ธโฃ-1)
ํฌ๊ฒ ๋ณด๋ฉด, BFS์ queue๋ฅผ ์ฐ์ ์์ ํ๋ก ๋ฐ๊พธ๋ ๊ฒ๊ณผ ๊ฐ๋ค.
BFS๋ ๋ฐฉ๋ฌธ ๋
ธ๋์ ์ธ์ ์ ์ ์ ๋นจ๋ฆฌ ์ ์ฅํ ์์ผ๋ก ๋ฐฉ๋ฌธํ๋ ๋ฐ๋ฉด, ์ฐ์ ์์ ํ๋ฅผ ์ฐ๋ฉด, dist ๊ฑฐ๋ฆฌ๊ฐ ์ต์์ธ ๋
์ ๋จผ์ ๋ฐฉ๋ฌธํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
(1) ์๊ฐ๋ณต์ก๋ ๋ถ์
๋
ธ๋์ ๊ฐ์: N
. ๊ฐ์ ์ ๊ฐ์: E
๋ผ๊ณ ํ์.
- 1๏ธโฃ ์ฐ์ ์์ ํ์์ ์ต์ ๋น์ฉ ๋
ธ๋ ๋ฝ๊ธฐ ($O(N log_10 N)$)
์ต์ ๋น์ฉ ๋ ธ๋๋ฅผ ์ฐ์ ์์ ํ์์ ๋บด๋ ํ์ ์์ฒด๊ฐ $O(N log_10 N)$๋ ๋ค. - 2๏ธโฃ ๋ชจ๋ ๊ฐ์ ์ ํ์ฉํ์ฌ ์ฐ์ ์์ ํ ์ต์ ํ ($O(E log_10 N)$)
๋ฐ๋ผ์ ์ด $O(N log_10 N + E log_10 N)$ ์ ์๊ฐ๋ณต์ก๋๊ฐ ๋ ๋ค.
(2) ์ ์ ์ ์ค๋ณต ๋ฐฉ๋ฌธํ๊ฒ ๋์ง ์์๊น..?
์ด๋ฏธ ์ฌ์ฉํ ๋ ธ๋๋ ๋ค์ ์ฌ์ฉํ์ง ์๋๋ค๋ ์๋ฏธ์ 3๏ธโฃ์ ๊ณผ์ ์ ์ถ๊ฐ ํด์ฃผ์๋ค.
A.dist๋ queue์ ๋ฃ์์ ๋น์, A๊น์ง์ ์ต์ ๋น์ฉ์ด๋ค. ๊ทผ๋ฐ ์ด๊ฒ์ด ๊ณ์ ์ต์๊ฐ์ผ๋ก ์ต์ ํ๋ฅผ ๊ฑฐ๋ญํ dist[A]์ ๋ค๋ฅด๋ค๋ฉด, A.dist๋ ์ด๋ฏธ ์ธ๋ชจ ์๋ ๊ณ ๋์ ์ ๋ฌผ์ธ ์ ์ด๋ค. ๋ฐ๋ผ์ ๋ถํ์ํ ๊ณ์ฐ์ด ํ์ ์๋๋ก ๋์ด๊ฐ๋ค.
(3) ๊ตฌํ ์ฝ๋
import java.io.*;
import java.util.*;
public class ์์ฐจํ์_๋ค์ต์คํธ๋ผ {
static int N = 9;
static int [] dist = new int [N];
static ArrayList<Vertex> [] lists;
public static void main(String[] args) throws IOException {
// 0. initialize
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
lists = new ArrayList [N+1];
Arrays.fill(dist, Integer.MAX_VALUE);
for(int i = 1; i < N+1; i++){
lists[i] = new ArrayList<>();
}
int edge_cnt = Integer.parseInt(br.readLin());
for(int i = 0; i < edge_cnt; i++){
StringTokenizer st = new StringTokenizer(br.readLine());
int start = Integer.parseInt(st.nextToken());
int end = Integer.parseInt(st.nextToken());
int cost = Integer.parseInt(st.nextToken());
lists[start].add(new Vertex(end, cost));
}
// 1๋ถํฐ ๋ชจ๋ ์ ์ ๊น์ง์ ์ต๋จ๊ฑฐ๋ฆฌ๋ฅผ ์ฐพ๊ฒ ๋ค.
Dijkstra(1);
}
// ์์๋
ธ๋๋ฅผ ์ธ์๋ก ๋ฐ์์, ํด๋น ๋
ธ๋๋ก๋ถํฐ ๋ชจ๋ ๋
ธ๋์ ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ dist์ ์
๋ ฅ
public void Dijkstra(int start) {
PriorityQueue<Vertex> pq = new PriorityQueue<>((o1,o2) -> o1.fast_cost - o2.fast_cost);
pq.add(new Vertex(start, 0));
while(!pq.isEmpty()){
Vertex now = pq.poll();
if(now.cost != dist[now.idx]) continue;
for(int i = 0; i < list[now.idx].size(); i++){
int dest_idx = list[now.idx].get(i).idx;
int compare_dist = list[now.idx].get(i).weight + dist[now.idx];
if(compare_dist < dist[dest_idx]){
dist[dest_idx] = compare_dist;
pq.add(new Vertex(dest_idx, compare_dist));
}
}
}
}
}
class Vertex {
int idx; // ํ ์ ์ ์ ๋ฒํธ
int cost; // ์์ ์ ์ ์์ ํ ์ ์ ๊น์ง์ ์ต๋จ ๊ฑฐ๋ฆฌ (ํ์ ์ง์ด๋ฃ์ ๋น์์ ์ต๋จ๊ฑฐ๋ฆฌ๋ผ์ ์ต์ ํ๋ dist ๋ฐฐ์ด๊ณผ ์ฐจ์ด๊ฐ ๋ ์ ์์)
public Vertex (int idx, int fast_cost){
this.idx = idx;
this.fast_cost = fast_cost;
}
(3) ์์
1.
2.
3.
4.
5.
์ด์ ๋ค์์ด ์ค์ํ๋ฐ, ์ด๋ฏธ ๋ฐฉ๋ฌธํ ์ ์ 4
๊ฐ ์ฐ์ ์์ ํ์ front์ ์์๋ค. ํ์ง๋ง ์๋ณด๋ฉด ์ ์ 4๊น์ง์ ์ต๋จ๊ฑฐ๋ฆฌ๋ผ ์ ์ฅํด๋์ ๊ฒ์ด 5
๋ก ์ด๋ฏธ ์ต์ ํ๋ ์ต๋จ ๊ฑฐ๋ฆฌ ๋ฐฐ์ด ์ dist[4]์ ๊ฐ๋ณด๋ค ํฌ๋ค. ๊ทธ๋์ queue.poll() ํ์๋ง์ ๋ฒ๋ฆฐ๋ค.
6.
7.
์ดํ ๋จ์ ์ ์ ์ dist ๊ฐ๋ ์ต์ ํ๋ dist ๋ฐฐ์ด(์ต๋จ ๊ฑฐ๋ฆฌ ๋ฐฐ์ด) ์ dist[6]๋ณด๋ค ๊ฐ์ด ํฌ๋ฏ๋ก ๊ทธ๋ฅ PASS ํ๋ค.