백_곰 2023. 5. 5. 21:08

1. 개념 설명

(1) 다익스트라는 그래프의 한 정점에서 모든 정점까지의 최단거리를 각각 구하는 알고리즘이다.

( 이것을 줄여서 최단 경로 알고리즘이라고 부른다. )

 

(2) 다익스트라는 그래프 방향의 유무는 상관없으나, 간선들 중 단 하나라도 가중치가 음수이면

이 알고리즘은 사용할 수 없다.

 

(3) 만약 음의 가중치를 가지는 간선이 있으며 가중치 합이 음인 사이클이 존재하지 않는 경우 벨만-포드

알고리즘을 사용한다.

( 또한 그래프 내에 가중치 합이 음인 사이클이 존재한다면, 무한히 음의 사이클을 도는 경우 합이 음수

무한대로 발산하기 때문에 최단 경로를 구성할 수 없다. )

 

 

 

2. 과정

by wiki

- 실제로 수행되는 과정이며, 특정한 정점에서 다른 모든 정점으로 가는 최단 경로를 기록하고 있다.

 

 

 

3. 입출력 조건 및 예제

입력 조건

(1) 첫째 줄에 정점의 개수 V와 간선의 개수 E, 시작 정점의 번호 K가 주어진다.

(3) 두 번째 줄부터 E개의 줄에 걸쳐 각 간선을 나타내는 세 개의 정수 (u, v, w)가 순서대로 주어진다. 

 

출력 조건

(1) 최단 경로의 경로값들을 출력한다.

( 시작점 자신은 0으로 출력하고, 경로가 존재하지 않는 경우에는 INF를 출력하면 된다. )

 

입력 예제

6 9 1
1 2 7
1 3 9
1 6 14
2 3 10
2 4 15
3 4 11
3 6 2
4 5 6
6 5 9
 

출력 예제

[2147483647, 0, 7, 9, 20, 20, 11]
 

 

 

4. 코드

( 아래의 코드는 위 그래프 그림을 보고 작성되었으며 같이 보면서 코드를 보는 것을 추천한다. )

class Node implements Comparable<Node>{
    int E, W;
    
    public Node(int E, int W) {
        this.E = E;
        this.W = W;
    }
    
    @Override
    public int compareTo(Node o) {
        // TODO Auto-generated method stub
        return this.W - o.W;
    }
}
 
public class Test {
    static int V, E, K;
    
    static ArrayList<Node>[] list;
    static int[][] map;
    static boolean[] visited;
    static int[] dist;
    
    static BufferedReader sc = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuilder sb = new StringBuilder();
    
    public static void main(String[] args) throws IOException {
        StringTokenizer st = new StringTokenizer(sc.readLine());
        V = Integer.parseInt(st.nextToken());
        E = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
        
        list = new ArrayList[V+1];
        dist = new int[V+1];
        visited = new boolean[V+1];
        
        Arrays.fill(dist, Integer.MAX_VALUE);
        for(int i=1; i<=V; i++) {
            list[i] = new ArrayList<>();
        }
        
        for(int i=1; i<=E; i++) {
            st = new StringTokenizer(sc.readLine());
            int u = Integer.parseInt(st.nextToken());
            int v = Integer.parseInt(st.nextToken());
            int w = Integer.parseInt(st.nextToken());
            
            list[u].add(new Node(v, w));
        }
        solve(K);
        System.out.println(Arrays.toString(dist));
    }
    
    static void solve(int start) {
           PriorityQueue<Node> queue = new PriorityQueue<>();
           queue.add(new Node(start, 0)); // 시작 정점과 시작 가중치 0을 넣는다.
           dist[start] = 0;
 
           while(!queue.isEmpty()){
               Node curNode = queue.poll();
               start = curNode.E;
 
               if(visited[start]) continue;
               visited[start] = true;
 
               for(Node node : list[start]){
                   if(dist[node.E] > dist[start] + node.W){
                       dist[node.E] = dist[start] + node.W;
                       queue.add(new Node(node.E, dist[node.E]));
                   }
               }
           }
    }
}
cs

 

 

 

 

5. 시간 복잡도

(1) 인접 행렬: O(N^2)

(2) 인접 리스트: O(N+logN)

( 이때, V는 정점, E는 간선을 의미한다. )

 

 

 

6. 장점

(1) 다익스트라 알고리즘은 벨만-포드 알고리즘에 비해 좀 더 효율적이기 때문에, 그래프가 큰 경우에도

사용할 수 있다.

 

 

 

7. 단점

(1) 위에서도 말했지만 다익스트라 알고리즘은 음수인 가중치를 가진 간선이 있는 겨웅에는 사용할 수 없다.

 

 

 

8. 관련 문제 풀어보기

 

1238번: 파티 (골드 3) (tistory.com)

 

1238번: 파티 (골드 3)

1238번: 파티 (acmicpc.net) 1238번: 파티 첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 10,000), X가 공백으로 구분되어 입력된다. 두 번째 줄부터 M+1번째 줄까지 i번째 도로의 시작점, 끝점, 그리고 이 도로를 지

kind-coding.tistory.com

1753번: 최단 경로 (골드 4) (tistory.com)

 

1753번: 최단 경로 (골드 4)

1753번: 최단경로 (acmicpc.net) 1753번: 최단경로 첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1 ≤ V ≤ 20,000, 1 ≤ E ≤ 300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘

kind-coding.tistory.com

 

 

9. 참고 사이트

다익스트라(Dijkstra) 알고리즘 | 👨🏻‍💻 Tech Interview (gyoogle.dev)

 

다익스트라(Dijkstra) 알고리즘 | 👨🏻‍💻 Tech Interview

다익스트라(Dijkstra) 알고리즘 다익스트라 알고리즘은 특정한 정점에서 다른 모든 정점으로 가는 최단 경로를 기록한다. 여기서 DP가 적용되는 이유는, 굳이 한 번 최단 거리를 구한 곳은 다시 구

gyoogle.dev