CS/알고리즘

Dijkstra - 데이크스트라(다익스트라)

lms0806 2023. 1. 22. 23:27
728x90
반응형

데이크스트라(Dijkstra)는 BFS 알고리즘을 알고 있다면 조금 더 쉽게 이해할 수 있다.

시작 지점 부터 가고자하는 도착지점까지 최소한의 시간으로 도착할 수 있는 거리를 구하는 알고리즘이다.

 

ex)https://www.acmicpc.net/problem/1916

 

1916번: 최소비용 구하기

첫째 줄에 도시의 개수 N(1 ≤ N ≤ 1,000)이 주어지고 둘째 줄에는 버스의 개수 M(1 ≤ M ≤ 100,000)이 주어진다. 그리고 셋째 줄부터 M+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그

www.acmicpc.net

예제 입력은 1번에서 출발하여 5번까지 도착하는데 걸리는 최소 시간을 구하는 문제입니다.

1 -> 4 -> 5을 이동하게 된다면 1 + 3 = 4의 시간이 걸리게 됩니다.

 

<JAVA>

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

public class Main {
	static int n;
	static int[] dist;
	static List<Node>[] list;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		n = Integer.parseInt(br.readLine());
		int m = Integer.parseInt(br.readLine());
		
		dist = new int[n + 1];
		list = new ArrayList[n + 1];
		
		Arrays.fill(dist, Integer.MAX_VALUE); // 현재 안간 노드들을 모두 최대시간 소요된다고 가정
		
		for(int i = 1; i <= n; i++) {
			list[i] = new ArrayList<>();
		}
		
		while(m --> 0) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			int a = Integer.parseInt(st.nextToken()), b = Integer.parseInt(st.nextToken());
			int cost = Integer.parseInt(st.nextToken());
			
			list[a].add(new Node(b, cost));
		}
		
		StringTokenizer st = new StringTokenizer(br.readLine());
		System.out.print(dijkstra(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())));
	}
	
	public static int dijkstra(int start, int end) {
		PriorityQueue<Node> queue = new PriorityQueue<>();
		queue.add(new Node(start, 0)); // 출발위치, 소요 시간 저장
		dist[start] = 0; // 출발 노드의 소요시간은 0
		
		while(!queue.isEmpty()) {
			Node now = queue.poll();
			
			if(dist[now.to] < now.weight) {
				continue;
			} // 현재까지 소요되는 최소시간이 지나온 거리의 길이보다 작으면 pass
				
			for(Node node : list[now.to]) {
				if(dist[node.to] > dist[now.to] + node.weight) {
					dist[node.to] = dist[now.to] + node.weight;
					queue.add(new Node(node.to, dist[node.to]));
				}//다음에 갈 노드까지의 최소시간이 현재 노드까지 걸린 시간 + 다음 노드까지의 거리보다 작으면 change
			}
		}
		return dist[end];
	}
}

class Node implements Comparable<Node>{
    int to, weight;

    public Node(int to, int weight){
        this.to = to;
        this.weight = weight;
    }

    @Override
    public int compareTo(Node o) {
        return this.weight - o.weight;
    }// 소요되는 시간을 기준으로 정렬
}

<C++>

#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>

using namespace std;

vector<pair<int, int>> arr[1001];
int dist[1001];
int s, e;
int n, m;

void dijkstra() {
	priority_queue<pair<int, int>> pq;
	pq.push({ 0, s });
	dist[s] = 0;

	while (!pq.empty()) {
		int weight = -pq.top().first;
		int cur = pq.top().second;
		pq.pop();

		if (dist[cur] < weight) {
			continue;
		}

		for (pair<int, int> next : arr[cur]) {
			int ncur = next.first;
			int nweight = next.second;

			if (dist[ncur] > dist[cur] + nweight) {
				dist[ncur] = dist[cur] + nweight;
				pq.push({ -dist[ncur], ncur });
			}
		}
	}\
}

int main()
{
	cin.tie(NULL)->sync_with_stdio(false);

	fill(dist, dist + 1001, 1e9);
	
	cin >> n >> m;

	int a, b, w;
	while (m--) {
		cin >> a >> b >> w;
		arr[a].push_back({ b, w });
	}
	
	cin >> s >> e;

	dijkstra();

	cout << dist[e];
}

 

추천 문제

https://www.acmicpc.net/problem/1504

 

1504번: 특정한 최단 경로

첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄에 걸쳐서 세 개의 정수 a, b, c가 주어지는데, a번 정점에서 b번 정점까지 양방향 길이 존

www.acmicpc.net

https://www.acmicpc.net/problem/1753

 

1753번: 최단경로

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

www.acmicpc.net

 

728x90
반응형