4. ๊ตฌํ
(1) ์์ฐจ ํ์
์ ๋ฒ ๊ฒ์๊ธ์์ ์ค๋ช
ํ ์๋์๋ฆฌ
๊ทธ๋๋ก ๊ตฌํํ ๋ฐฉ์์ด๋ค.
๋ฐฉ๋ฌธํ ์ ์ ๊ณผ ๊ทธ๋ ์ง ์์ ์ ์ ๊ตฌ๋ถ์ ์ํด์, ๋ฐฉ๋ฌธ๋ฐฐ์ด์ ์ฌ์ฉํ๋ค.
ํ์ฌ ์ ์ ์์ ๊ฐ ์ ์๋ ๊ฐ์ ์ ํตํด dist[] ๋ฐฐ์ด์ ์ต์ ํํ๊ณ , ๋ฐฉ๋ฌธ ๋ฐฐ์ด์ ํตํด, ํ์ฌ๊น์ง ๋ฐฉ๋ฌธํ์ง ์์ ์ ์ ์ค ์์ ์ ์ ์์ ์ต๋จ ๊ฑฐ๋ฆฌ๋ก ๊ฐ ์ ์๋ ์ ์ ์ ํํด์ผ ํ๋ค.
์ฌ๊ธฐ์ ์ต์
์ ๊ฒฝ์ฐ, ์ ์ ์ ์๊ฐ N๊ฐ๋ผ๋ฉด, ๋งค๋ฒ N๋ฒ์ ์ ์ ์ ํ์ํด ๋ค์ ๋ฐฉ๋ฌธํด์ผํ ์ ์ ์ ์ฐพ์์ผ ํ๊ณ , ์ด ํ์๋ฅผ ๋ชจ๋ ์ ์ ์ ๋ฐฉ๋ฌธํ ๋๊น์ง ๋ฐ๋ณตํด์ผ ํ๋ฏ๋ก ์ต์
์ ์๊ฐ๋ณต์ก๋๋ O(N^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) ์ฐ์ ์์ ํ ํ์ฉ
โ
๊ตฌํ ๋ฐฉ๋ฒ โ
/*
0. ์ธ์ ๋ฆฌ์คํธ, ์ต๋จ ๊ฑฐ๋ฆฌ ๋ฐฐ์ด ์ต์ ํ
1. ์ ์ ๊ฐ์ฒด์ ์์๋
ธ๋๋ก๋ถํฐ์ ๊ฑฐ๋ฆฌ๊ฐ ์งง์ ์์ผ๋ก ์ ๋ ฌ๋๋ ์ฐ์ ์์ ํ ์์ฑ
1-1 ํด๋น ์ฐ์ ์์ ํ์ ์์ ์ ์ ์ ๋ฃ๊ณ '์ฐ์ ์์ ํ'๊ฐ ๋น ๋๊น์ง ๋ฐ๋ณต๋ฌธ ์์
2. Node curNode = queue.poll() ํ์ฌ ํ์ฌ ๋ฐฉ๋ฌธํ๋ ค๋ ์ ์ ๊บผ๋ด๊ธฐ
2-1. if(dist[curNode.idx] < curNode.cost) continue; ๋ฅผ ํตํด ์ ํจ์ฑ ํ์ธ
2-2. ํ์ฌ ๋ฐฉ๋ฌธ ์ค์ธ ์ ์ ์ด ์ ํจํ๋ค๋ฉด ์ด๋ฅผ ์ด์ฉํด ์ต๋จ ๊ฑฐ๋ฆฌ ๋ฐฐ์ด ๊ฐฑ์
2-3. ๊ฐฑ์ ๋ ์ ์ ๋ง ๋ค์ queue์ ๋ฃ๊ธฐ.
*/
a. ์ฐ์ ์์ ํ์ ์ญํ
์ฐ์ ์์ ํ๋ ๋ฐฉ๋ฌธ๋ฐฐ์ด ๋์ฉ
์ญํ ์ด๋ค.
ํ ๋ฒ ์ต๋จ ๊ฑฐ๋ฆฌ ๋ฐฐ์ด(dist)์ ๊ฐฑ์ ํ ๋๋ง๋ค ๋ค์ ๋ฐฉ๋ฌธํ ๋
ธ๋๋ฅผ O(N^2)์ ์๊ฐ ๋ณต์ก๋๋ก ๋ฐฉ๋ฌธํด์ผ ํ๋ ๊ฒ์ ๋นํด ์์๋
ธ๋๋ก ๋ถํฐ ์ต๋จ ๊ฑฐ๋ฆฌ์ธ Node ์์ผ๋ก ์ ๋ ฌ
ํ ์ฐ์ ์์ ํ๋ฅผ ์ด๋ค๋ฉด, ๊ทธ์ queue.poll()ํ ๊ฐ์ ๊บผ๋ด ์ฐ๋ฉด ๋๋ฏ๋ก ์๊ฐ ๋ณต์ก๋๋ฉด์์ ํฌ๊ฒ ํจ์จ์ด ์์นํ๋ค. (์ผ๋ง๋ ์์นํ๋์ง๋ ํ์ ํ๊ฒ ๋ค.)
b. Node ๊ฐ์ฒด ์ cost์ 2๊ฐ์ง ์๋ฏธ
์ผ๋จ Node๋ผ๋ ํด๋์ค๋ฅผ ์ ์ํ๊ฒ ๋ค.
class Node {
int idx; // ์ ์ ๋ฒํธ
int cost; // ์ธ์ ๋ฆฌ์คํธ์์๋ ๊ฐ์ ์ ๊ฐ์ค์น, ๋ค์ต์คํธ๋ผ ๋ด๋ถ์์๋ ํ์ฌ ๊ฐฑ์ ๋ dist ๊ฐ
}
์์ ๊ฐ์ด 2๊ฐ์ง ์๋ฏธ๋ก ๊ตฌ๋ถ๋์ด ์ฐ์ธ๋ค.
- ์ธ์ ๋ฆฌ์คํธ ๊ตฌํ ์ ํด๋น Node ์ cost๋ ๋ฉค๋ฒ๋ณ์๋ ๊ฐ์ ์ ๊ฐ์ค์น๋ก ์ฐ์.
- ๋ค์ต์คํธ๋ผ ๋ด๋ถ์์ ์ฌ์ฉ๋๋ Node ๊ฐ์ฒด์ cost๋ ๊ฐฑ์ ๋ dist ๊ฐ์ ๊ฐ๋ฅดํด.
1๋ฒ์ ๋น์ฐํ๋๊น ๋์ด๊ฐ์. 2๋ฒ์ ๋ฌด์จ ์๋ฏธ์ธ๊ฐ? ๋จผ์ ์ฐ์ ์์ํ ํ์ฉํ ๋ค์ต์คํธ๋ผ์ ์์๋ฅผ ๋ณด์ฌ์ฃผ๊ฒ ๋ค.
// ์์๋
ธ๋๋ฅผ ์ธ์๋ก ๋ฐ์์, ํด๋น ๋
ธ๋๋ก๋ถํฐ ๋ชจ๋ ๋
ธ๋์ ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ dist์ ์
๋ ฅ
public void Dijkstra(int start) {
PriorityQueue<Node> pq = new PriorityQueue<>((o1,o2) -> o1.fast_cost - o2.fast_cost);
pq.add(new Node(start, 0));
while(!pq.isEmpty()){
Node 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 Node(dest_idx, compare_dist));
}
}
}
}
์ฌ๊ธฐ์ ๋งจ ๋ง์ง๋ง if๋ฌธ์ ๋ณด๋ฉด, ํ์ฌ ํ์ธ ์ค์ธ ์ ์ ์ ํ์ฉํ ๊ฑฐ๋ฆฌ ๋น์ฉ
์ด ๊ธฐ์กด ๋น์ฉ
๋ณด๋ค ์์ผ๋ฉด ๊ฐฑ์ ํ๋ ๋ชจ์ต์ ๋ณผ ์ ์๋ค. ๋ํ ์๋ก์ด Node ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ๋ค์ queue์ ์ฝ์
ํ๋ค. ์์ ๊ฐ์ด ๋ค์ต์คํธ๋ผ ๋ด๋ถ ์ฐ์ ์์ํ์ ์ ๋ ฌ๊ธฐ์ค์ ๋ง์ถฐ ๋ค์ ์ ์ ์ ์ฐพ๊ธฐ ์ํด
์ฌ๊ธฐ์์ Node.cost๋ ํ์ฌ ๊ฐฑ์ ๋ ์ต๋จ ๊ฑฐ๋ฆฌ ๋น์ฉ์ ๋ปํ๋ค.
c. if(dist[curNode.idx] < curNode.cost) continue
ํ๋ ์ด์ ?
ํ์ง๋ง ์์ ๊ฐ์ด ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ cost๋ก ๊ฐ์ง ๊ฐ์ฒด๋ฅผ ์ฐ์ ์์ ํ์ ๋ฃ๋๋ค๊ณ ํด์, ๋ฐฉ๋ฌธ ๋ฐฐ์ด ํ์ฉ ๋ค์ต์คํธ๋ผ๋ณด๋ค ์๋๋ฉด์์ ํจ์จ์ ์ด๋ผ ๋ณผ ์ ์๋ค. ์๋ํ๋ฉด queue.poll()ํ ๊ฐ์ฒด A์ cost
> dist[A.idx]์ cost
์ผ ๊ฒฝ์ฐ ์ฆ, ํ์ฌ ๋ฐฉ๋ฌธํ๋ ค๋ ์ ์ ์ด ์ฃผ์ฅํ๋ dist ๊ฐ๋ณด๋ค dist ๋ฐฐ์ด์ ๊ฐฑ์ ๋ ๊ฐ์ด ๋ ์๋ค๋ฉด,
์ด๋ฏธ ํด๋น ์ ์ ์ ์ด์ poll()ํ ๊ฐ์ฒด์ ์ํด ๋ ๋จ๊ฑฐ๋ฆฌ ์ต๋จ๋น์ฉ์ผ๋ก ๊ฐฑ์ ๋์๋ค๋ ์๋ฆฌ์ด๋ค. ์ด๋ฏธ ๋ ์์ ๊ฐ์ผ๋ก ๊ฐฑ์ ๋์๋๋ฐ, ํ์ฌ ์ ์ ๋น์ฉ์ผ๋ก ๋ค์ ๊ณ์ฐํ๋ ๊ฒ์ ๋ฌด์๋ฏธํ๋ค. ๋ฐ๋ผ์ ํด๋น ๊ฒฝ์ฐ๋ ๋์ด๊ฐ๋๋ก ์กฐ์น๋ฅผ ์ทจํด์ค๋ค.
d. ์๊ฐ๋ณต์ก๋๋? ๐ค๐ญ
์ฐ์ ์์ ํ ํ์ฉ ๋ค์ต์คํธ๋ผ๋ ์ฐ์ ์์ ํ ํ์ฉ ๋ถ๋ถ๋ง ๋บ๋ค๋ฉด 1๋จ ๋ฐ๋ณต๋ฌธ๊ณผ ์กฐ๊ฑด๋ฌธ์ผ๋ก๋ง ์ด๋ฃจ์ด์ ธ ์๊ธฐ ๋๋ฌธ์, ์ฐ์ ์์ ํ ํ์ฉ์ด ์๊ฐ์ด ์ ์ผ ๋ง์ด ๋ ๋ค. ๋ฐ๋ผ์ ์ฐ์ ์์ ํ ํ์ฉ๋ถ๋ถ๋ง ์๊ฐํด์ฃผ๋ฉด ๋๋ค. N๊ฐ์ ๊ฐ์ ์ฐ์ ์์ํ์ ์ฝ์
ํ๋ค๋ฉด O(logN)
์ ์๊ฐ์ด ๋ ๋ค. ์ถ์ถ ์์๋ ๋ง์ฐฌ๊ฐ์ง๋ก O(logN)
์ ์๊ฐ์ด ๋ ๋ค.
์ ์ ์ ์๋ฅผ V, ๊ฐ์ ์ ์๋ฅผ E๋ผ ํ ๋, ์ฝ์
์ ์ผ๋ง๋ ์ด๋ฃจ์ด์ง๊น? ์ฐ์ ์์ ํ ์ฝ์
์ ์ต๋จ ๊ฑฐ๋ฆฌ ๋ฐฐ์ด์ด ๊ฐฑ์ ๋ ๋๋ง ์ด๋ฃจ์ด์ง๋ค. ์ต์
์ ๊ฒฝ์ฐ, ํ์ฌ ๋ฐฉ๋ฌธํ ์ ์ ์์ ๊ฐ ์ ์๋ ์ ์ ์ ๊ณ ๋ คํ ๋๋ง๋ค ๊ฐฑ์ ๋ ๊ฒ์ด๋ฏ๋ก ๊ฐ์ ์ ์๋งํผ ์ฝ์
๋ ๊ฒ์ด๋ค. ๋ฐ๋ผ์ O(ElogE)
์ ์๊ฐ ๋ณต์ก๋๊ฐ ํ์ํ๋ค. ๋ฐ์ง ๊ทธ๋ํ๊น์ง ๊ฐ์ ํ๋ค๋ฉด E <= V^2 ๊ฐ๊น์ง ๊ฐ๋ฅํ๋ฏ๋ก O(ElogV^2), O(2*ElogV) ์ฆ O(ElogV)
๋ก๋ ํํ์ด ๊ฐ๋ฅํ๋ค.
์ถ์ถ์ ๋น์ฐํ Queue๊ฐ ๋น๋๊น์ง ๊ณ์ ๋์ด์ผ ํ๋ค. Queue์๋ ์ต์ ์ ์ ์ ๊ฐ์, ์ต๋๋ก ๋ง์๋ ๊ฐ์ ์ ์ต๋๊ฐ์ธ ์ ์ ์ ๊ฐ์์ ์ ๊ณฑ์ ๋์ง ์์ ๊ฒ์ด๋ค. ๋ฐ๋ผ์ ์๊ฐ๋ณต์ก๋๋ O(VlogV)
์ด๋ค. ๋์ ํฉ์น๋ฉด ์ต์ข
์ ์ผ๋ก
O((V+E)logV)
์ ์๊ฐ๋ณต์ก๋๋ฅผ ํ์๋ก ํ๋ค.
a. ์์
1.
2.
3.
4.
5.
์ด์ ๋ค์์ด ์ค์ํ๋ฐ, ์ด๋ฏธ ๋ฐฉ๋ฌธํ ์ ์ 4
๊ฐ ์ฐ์ ์์ ํ์ front์ ์์๋ค. ํ์ง๋ง ์๋ณด๋ฉด ์ ์ 4๊น์ง์ ์ต๋จ๊ฑฐ๋ฆฌ๋ผ ์ ์ฅํด๋์ ๊ฒ์ด 5
๋ก ์ด๋ฏธ ์ต์ ํ๋ ์ต๋จ ๊ฑฐ๋ฆฌ ๋ฐฐ์ด ์ dist[4]์ ๊ฐ๋ณด๋ค ํฌ๋ค. ๊ทธ๋์ queue.poll() ํ์๋ง์ ๋ฒ๋ฆฐ๋ค.
6.
7.
์ดํ ๋จ์ ์ ์ ์ dist ๊ฐ๋ ์ต์ ํ๋ dist ๋ฐฐ์ด(์ต๋จ ๊ฑฐ๋ฆฌ ๋ฐฐ์ด) ์ dist[6]๋ณด๋ค ๊ฐ์ด ํฌ๋ฏ๋ก ๊ทธ๋ฅ PASS ํ๋ค.
b. ๊ตฌํ
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;
}
}