다익스트라

  • 다익스트라 알고리즘은 그래프에서 최단 거리를 구하는 알고리즘이다.

    • 출발 노드와 모든 노드 간의 최단 거리 탐색

    • 에지는 모두 양수

    • O(ElogV) (노드 수 : V, 에지 수 : E)

dijkstra 알고리즘의 핵심 이론

  1. 인접 리스트로 그래프 구현하기

  2. 최단 거리 배열 초기화하기

  3. 값이 가장 작은 노드 고르기

  4. 최단 거리 배열 업데이트하기

  5. 과정 3~4를 반복하여 최단 거리 배열 완성하기

최단 경로 구하기

Question - 1753

Code

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class N56_P1753_최단_경로_구하기 {

    public static int node, edge, start;

    public static int distance[];
    public static boolean visited[];

    public static ArrayList<Edge> list[];
    public static PriorityQueue<Edge> pq = new PriorityQueue<Edge>();

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        st = new StringTokenizer(br.readLine());

        node = Integer.parseInt(st.nextToken());
        edge = Integer.parseInt(st.nextToken());
        start = Integer.parseInt(br.readLine()); //주의 !!!!!!!!!11

        distance = new int[node + 1];
        visited = new boolean[node + 1];

        list = new ArrayList[node + 1];
        for (int i = 1; i <= node; i++) {
            list[i] = new ArrayList<Edge>();
        }

        for (int i = 0; i <= node; i++) {
            // 얘는 왜 0부터 해주는 거임 ?
            distance[i] = Integer.MAX_VALUE; // 정수의 최댓값 출력
        }

        // u : 에서
        // v  : 로 가는
        // w : 가중치
        for (int i = 0; i < edge; i++) {
            st = new StringTokenizer(br.readLine());
            int u = Integer.parseInt(st.nextToken());
            int v = Integer.parseInt(st.nextToken());
            int w = Integer.parseInt(st.nextToken());
            list[u].add(new Edge(v, w));
        }

        pq.add(new Edge(start, 0));
        distance[start] = 0;

        while (!pq.isEmpty()) {
            Edge current = pq.poll();
            int CtoV = current.vertex;
            if (visited[CtoV]) continue;
            visited[CtoV] = true;

            for (int i = 0; i < list[CtoV].size(); i++) {
                Edge temp = list[CtoV].get(i);
                int next = temp.vertex;
                int value = temp.value;

                if (distance[next] > distance[CtoV] + value) {
                    distance[next] = value + distance[CtoV];
                    pq.add(new Edge(next, distance[next]));
                }
            }

        }
        for (int i = 1; i <= node; i++) {
            if (visited[i]) {
                System.out.println(distance[i]);
            } else {
                System.out.println("INF");
            }
        }
    }
}

class Edge implements Comparable<Edge> {
    int vertex, value;

    Edge(int vertex, int value) {
        this.vertex = vertex;
        this.value = value;
    }

    public int compareTo(Edge e) {
        if (this.value > e.value) return 1;
        else return -1;
    }
}
j

Idea

reference

최소 비용 구하기

Question - 1916

Code

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class N57_P1916_최소_비용_구하기 {

    static int node, edge; // country, bus

    static ArrayList<Node>[] list; // 인접 리스트로 그래프 표현하기
    static int[] dist; //최단거리 배열 distance
    static boolean[] visit; // 사용 노드인지 확인 visited

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st;

        node = Integer.parseInt(br.readLine());
        edge = Integer.parseInt(br.readLine());

        dist = new int[node + 1];
        visit = new boolean[node + 1];
        Arrays.fill(dist, Integer.MAX_VALUE); // 거리 배열을 충분히 큰 수로 초기화

        list = new ArrayList[node + 1]; //ArrayList<>[]아님 주의
        for (int i = 0; i <= node; i++) { //또 채워줌 0
            list[i] = new ArrayList<Node>();
        }

        for (int i = 0; i < edge; i++) {
            st = new StringTokenizer(br.readLine());
            int start = Integer.parseInt(st.nextToken());
            int end = Integer.parseInt(st.nextToken());
            int price = Integer.parseInt(st.nextToken());
            list[start].add(new Node(end, price));
        }

        st = new StringTokenizer(br.readLine());
        int startCountry = Integer.parseInt(st.nextToken());
        int endCountry = Integer.parseInt(st.nextToken());

        bw.write(dijkstra(startCountry, endCountry) + "\n");

        bw.flush();
        bw.close();
        br.close();
    }

    public static int dijkstra(int start, int end) {
        PriorityQueue<Node> pq = new PriorityQueue<>();
        pq.offer(new Node(start, 0));
        dist[start] = 0;

        while (!pq.isEmpty()) {
            Node nowNode = pq.poll();
            int now = nowNode.targetNode;
            if (!visit[now]) {
                visit[now] = true;
                for (Node n : list[now]) {
                    if (!visit[n.targetNode] &&
                            dist[n.targetNode] > dist[now] + n.value) {
                        dist[n.targetNode] = dist[now] + n.value;
                        pq.add(new Node(n.targetNode, dist[n.targetNode]));
                    }
                }
            }
        }
        return dist[end];
    }
}

class Node implements Comparable<Node> {
    int targetNode;
    int value;

    Node(int targetNode, int value) {
        this.targetNode = targetNode;
        this.value = value;
    }

    @Override
    public int compareTo(Node o) {
        return value - o.value;
    }
}

Idea

reference

K번째 최단 경로 찾기

Question - 1854

Code

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class N58_P1854_K번째_최단_경로_찾기 {

    static final int INF = 100000000;
    public static void main(String[] args) throws IOException {
        int node, edge, k;
        int[][] w = new int[1001][1001];

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());

        node = Integer.parseInt(st.nextToken());
        edge = Integer.parseInt(st.nextToken());
        k = Integer.parseInt(st.nextToken());

        PriorityQueue<Integer>[] distQueue = new PriorityQueue[node + 1];
        Comparator<Integer> cp = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 < o2 ? 1 : -1;
            }
        };
        for (int i = 0; i < node + 1; i++) { // node + 1
            distQueue[i] = new PriorityQueue<Integer>(k, cp);
        }

        for (int i = 0; i < edge; i++) {
            st = new StringTokenizer(br.readLine());
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            w[a][b] = c;
        }

        PriorityQueue<tNode> pq = new PriorityQueue<>();
        pq.add(new tNode(1, 0));
        distQueue[1].add(0);
        while (!pq.isEmpty()) {
            tNode u = pq.poll();
            for (int adjNode = 1; adjNode <= node; adjNode++) {
                if (w[u.node][adjNode] != 0) {
                    // 저장된 경로가 k개 안될 떄는 그냥 추가
                    if (distQueue[adjNode].size() < k) {
                        distQueue[adjNode].add(u.cost + w[u.node][adjNode]);
                        pq.add(new tNode(adjNode, u.cost + w[u.node][adjNode]));
                    }

                    // 저장된 경로가 k개이고, 현재 가장 큰 값보다 작을 때만 추가
                    else if (distQueue[adjNode].peek() > u.cost + w[u.node][adjNode]) {
                        distQueue[adjNode].poll();
                        distQueue[adjNode].add(u.cost + w[u.node][adjNode]);
                        pq.add(new tNode(adjNode, u.cost + w[u.node][adjNode]));
                    }
                }
            }
        }

        for (int i = 1; i <= node; i++) {
            if (distQueue[i].size() == k) {
                bw.write(distQueue[i].peek() + "\n");
            } else {
                bw.write(-1 + "\n");
            }
        }

        bw.flush();
        bw.close();
        br.close();
    }
}

class tNode implements Comparable<tNode> {
    int node;
    int cost;

    tNode(int node, int cost) {
        this.node = node;
        this.cost = cost;
    }

    @Override
    public int compareTo(tNode o) {
        return this.cost < o.cost ? -1 : 1;
    }
}

Idea

reference

Last updated