Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
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
Archives
Today
Total
관리 메뉴

두's 스토리

다익스트라 본문

알고리즘

다익스트라

알 수 없는 사용자 2019. 8. 1. 16:27

다익스트라

  • 한 정점에서 다른 끝점 까지 가는 최단거리를 구할 때 사용

  • 플로이드 워셜 알고리즘은 정점 전부에 관한 정보를 업데이트하여 N^3이란 시간복잡도를 가진다. (=AllPairShortest)

  • 그러나, 다익스트라는 시작점을 고정하고 DP배열을 업데이트 하는 방식을 통해 n^2이란 시간복잡도를 가짐.

  • 다익스트라에서 최종적으로 나온 DP 배열은 시작점에서 그 점까지의 거리를 의미

     

     

    NODE 1 2 3 4 5
    DP 0 3 5 INF 8
    • 다음 표처럼 시작점을 정해주고 모든 점에 대해 DP를 업데이트하면 최단거리를 구할 수 있음

    • 1에서 3까지의 거리는 5, 1에서 4까지의 거리는 INF를 의미

       

       

       

       

백준 1753 최단경로

  • 일반적으로 인접행렬 W 을 이용하여 DP를 업데이트
방문노드 1 2 3 4 5
  INF INF INF INF INF
{1} 0(자기자신0) INF INF INF INF
{1, 2} 0

2(MIN(

D[2], D[2]+W[2][2]

3 INF INF
{1, 2, 3} 0 2 3

7(MIN(

D[4], D[3]+W[3][4]

INF
{1, 2, 3, 4} 0 2 3 7 INF
  • 그러나 위 문제 같은 경우 인접행렬을 이용하여 업데이트시 메모리 초과 -> 우선순위 큐를 이용한 풀이

     

  • /*매 턴마다 방문한 node와 관련된 list.get(now)만 점검 -> 최소값이 갱신될경우 pq에 추가 -> pq는  

 * 자동정렬되어 그 턴 중 가장 작은 distance(dp)값을 가지는 node를 앞으로 땡겨줌(즉, distance가 최소인 노드 먼저 방문 가능)
 *  
 *          1      2      3      4     5           pq                push                     update
 *  INF  0   INF INF INF INF      {1, 0}        {2, 2}, {3,3}          {1, 2, 2}, {1, 3, 3} 사용
 *  INF  0     2      3   INF INF      {2, 2}        {3, 3}, {4, 7}         {2, 3, 5}, {2, 4, 4} 사용
 *  INF  0     2      3     7    INF      {3, 3}            {4, 7}                {3, 4, 6} 사용
 *  INF  0     2      3     7    INF      {4, 7}
 */

import java.util.ArrayList;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Scanner;
class D implements Comparable{
	int end;
	int distance;
	D(int end, int distance) {
		this.end = end;
		this.distance = distance;
	}
	@Override
	public int compareTo(D o) {
		return this.distance - o.distance;
	}
}
public class Main {
	public static void main(String[] args) {
		Scanner s = new Scanner(System.in);
		int V = s.nextInt();
		int E = s.nextInt();
		int st = s.nextInt();
		
		ArrayList<ArrayList> list = new ArrayList<>();
		for(int i=0; i<=V; i++)	
			list.add(new ArrayList<>());
		for(int i=0; i<E; i++) {
			int u = s.nextInt();
			int v = s.nextInt();
			int w = s.nextInt();
			list.get(u).add(new D(v, w));
		}
		int distance[] = new int[V+1];
		Arrays.fill(distance, 999999);
		boolean visited[] = new boolean[V+1];
		PriorityQueue pq = new PriorityQueue(); //우선순위 큐에는 업데이트 되는 distance를 넣음. 
		distance[st] = 0;
		pq.add(new D(st, 0));
		
		/*매 턴마다 방문한 node와 관련된 list.get(now)만 점검 -> 최소값이 갱신될경우 pq에 추가 -> pq는 
		 * 자동정렬되어 그 턴 중 가장 작은 distance(dp)값을 가지는 node를 앞으로 땡겨줌(즉, distance가 최소인 노드 먼저 방문 가능)
		 *  
		 *          1      2      3      4     5           pq                push                     update
		 *  INF  0   INF INF INF INF      {1, 0}        {2, 2}, {3,3}          {1, 2, 2}, {1, 3, 3} 사용
		 *  INF  0     2      3   INF INF      {2, 2}        {3, 3}, {4, 7}         {2, 3, 5}, {2, 4, 4} 사용
		 *  INF  0     2      3     7    INF      {3, 3}            {4, 7}                {3, 4, 6} 사용
		 *  INF  0     2      3     7    INF      {4, 7}
		 */
		while(!pq.isEmpty()) {  //사실 while문이 전부
			int now = pq.poll().end;
			if(visited[now]) continue;  //이미 방문한 노드일경우 skip
			visited[now] = true;	
			
			for(D node: list.get(now)) {
				if(distance[node.end]>distance[now]+node.distance) {
					distance[node.end] = distance[now]+node.distance;
					pq.add(new D(node.end, distance[node.end]));
				}
			}
		}
		for(int i=1; i<distance.length; i++) {
			if(distance[i]==999999)
				System.out.println("INF");
			else
				System.out.println(distance[i]);
		}
	}
}

'알고리즘' 카테고리의 다른 글

Knapsack  (0) 2019.07.30
순열 & 조합  (0) 2019.07.26
이진검색  (0) 2019.07.22