Development/Algorithm

[알고리즘 정리] Dijkstra(다익스트라)

dia_0108 2020. 5. 3. 21:08

 

 

다룰 내용

  • Dijkstra 알고리즘
  • 벨만 포드 알고리즘

 


 

Dijkstra 알고리즘

시작 정점에서 거리가 최소인 정점을 선택해가면서 최단 경로를 구하는 알고리즘으로 탐욕 기법을 이용하는 Prim 알고리즘과 유사합니다. 그러나 다익스트라의 경우 근시안적인 관점 때문에 음의 가중치가 있다면 사용할 수 없습니다.

 

 

Dijkstra 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class Dijkstra {

	public static class Vertex implements Comparable<Vertex>{
		int v, weight;

		public Vertex(int v, int weight) {
			this.v = v;
			this.weight = weight;
		}

		@Override
		public int compareTo(Vertex o) {
			return Integer.compare(this.weight, o.weight);
		}
	}
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int V = Integer.parseInt(br.readLine());
		int end = V - 1;
		int adj[][] = new int[V][V];
		int d[] = new int[V];

		for(int i = 0; i < V; i++) { 
			String input2[] = br.readLine().split(" ");
			for(int j = 0; j < V; j++) {
				adj[i][j] = Integer.parseInt(input2[j]);
			}
		}

		boolean visited[] = new boolean[V];

		Arrays.fill(d, Integer.MAX_VALUE);

		//시작점이 a정점이라면 d[a] = 0;
		d[0] = 0;

		int min = 0, cur = 0;
		for(int i = 0; i < V; i++) {
			
			min = Integer.MAX_VALUE;
			
			for(int j = 0; j < V; j++) {
				if(!visited[j] && d[j] < min) {
					min = d[j];
					cur = j;
				}
			}
			
			if(visited[cur]) continue;
			visited[cur] = true;
			if(cur == end) break;

			for(int j = 0; j < V; j++) {
				if(!visited[j] && adj[cur][j] != 0 && min + adj[cur][j] < d[j]) {
					d[j] = min + adj[cur][j];
				}
			}
		}
		System.out.println(d[end]);
	}
}

 

 

Dijkstra + PQ(Priority Queue)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.PriorityQueue;

public class Dijkstra_pq {

	public static class Vertex implements Comparable<Vertex>{
		int v, weight;

		public Vertex(int v, int weight) {
			this.v = v;
			this.weight = weight;
		}

		@Override
		public int compareTo(Vertex o) {
			return Integer.compare(this.weight, o.weight);
		}
	}
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int V = Integer.parseInt(br.readLine());
		int end = V - 1;
		int adj[][] = new int[V][V];
		int d[] = new int[V];

		for(int i = 0; i < V; i++) { 
			String input2[] = br.readLine().split(" ");
			for(int j = 0; j < V; j++) {
				adj[i][j] = Integer.parseInt(input2[j]);
			}
		}

		boolean visited[] = new boolean[V];

		Arrays.fill(d, Integer.MAX_VALUE);

		//시작점이 a정점이라면 d[a] = 0;
		d[0] = 0;
		
		PriorityQueue<Vertex> q = new PriorityQueue<Vertex>();
		q.offer(new Vertex(0, d[0]));
		
		while(!q.isEmpty()) {
			
			Vertex cur = q.poll();
			
			if(visited[cur.v]) continue;
			visited[cur.v] = true;
			if(cur.v == end) break;

			for(int i = 0; i < V; i++) {
				if(!visited[i] && adj[cur.v][i] != 0 && cur.weight + adj[cur.v][i] < d[i]) {
					d[i] = cur.weight + adj[cur.v][i];
					q.offer(new Vertex(i, d[i]));
				}
			}
		}
		System.out.println(d[end]);
	}
}

 

 


 

벨만 포드 알고리즘

음의 가중치를 포함하느 그래프에서 최단 경로를 구할 수 있습니다. 단, 가중치의 합이 음인 사이클은 허용하지 않습니다.