알고리즘

다익스트라(dijkstra) 알고리즘

E재HO 2022. 8. 29. 00:04

다익스트라는 임의의 한 정점에서 다른 모든 정점까지의 최단 거리를 구하는 알고리즘이다. 

작동원리는 임의의 한 점에서 다른 한 점까지 최단 거리를 갱신해주는 것이다.

최단 거리는 여러 정점을 타고 수차례 갱신될 수 있다. 

 

이 설명은 그림이 좀 많이 필요한데 시간이 없다. 내일 시험이라서 나중에 수정해서 올리겠다. (여유가 생기면)

혹시 그럴 일은 없겠지만 내 블로그 애청자가 있다면 쪽지보내면 직접 설명 해주겠다.

 

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

package practice2;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.PriorityQueue;

class info implements Comparable<info>{
	int vertex,val;

	public info(int vertex, int val) {
		this.vertex = vertex;
		this.val = val;
	}

	@Override
	public int compareTo(info o) {
		return Integer.compare(this.val, o.val);
	}
}

public class boj1197 {
	static int N, M, S, answer;
	static int D[];
	static ArrayList<ArrayList<info>> list;
	static PriorityQueue<info> pq;
	public static void main(String[] args) throws IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		String[] s = in.readLine().split(" ");
		N = Integer.parseInt(s[0]);
		M = Integer.parseInt(s[1]);
		S = Integer.parseInt(in.readLine());
		
		D = new int[N+1];
		pq = new PriorityQueue<info>();
		
		list = new ArrayList<>();
		for(int i =0; i<=N;i++)list.add(new ArrayList<info>());
		
		for (int i = 0; i < M; i++) {
			s = in.readLine().split(" ");
			int from = Integer.parseInt(s[0]);
			int to = Integer.parseInt(s[1]);
			int val = Integer.parseInt(s[2]);
			list.get(from).add(new info(to,val));
		}
		
		Arrays.fill(D, Integer.MAX_VALUE);
		D[S]=0;
		pq.add(new info(S,0));
		
		while(!pq.isEmpty()) {
			int cur = pq.peek().vertex;//현재 정점
			int dist = pq.peek().val;//현재 정점까지의 비용
			pq.poll();
			
			if(dist<D[cur])continue;//이미 갱신이 된 노드라면 넘어간다.
			//pq에는 넣은 순서대로 나오지 않기 때문에 나중에 나온 값이 이미 갱신이 되어버렸을 수도 있다.
			//뿐만 아니라 다른 정점에서  D[cur]로 가는 것에 대해 값을 갱신을 해버렸을 경우도 있기 때문에 이와 같은 구조로 가지치기를 해야한다.
			//이 노드까지 오는 값이 갱신이 되었다고 가정해보자. 어디를 경유해서 현재 cur노드에 온것이다.
			//그 값이 이cur과 dist가 들어 갈 때의 값보다 더 작아진 상태면 무조건 현재의 D[cur]에 적혀있는 경로로 오는게 제일 짧다.
			//다익스트라는 갱신된 노드에 대해서는 다시 갱신을 하지 않는다.
			
			for(int i=0; i<list.get(cur).size(); i++) {
				int nextVertex = list.get(cur).get(i).vertex;//다음 정점
				int val = list.get(cur).get(i).val;//다음 정점으로 가는 비용
				if(D[nextVertex]>dist+val) {//다음 정점 가는것보다 현재정점까지 오는 비용에서 다음정점으로 가는 비용을 합친게
					//더 크다면
					D[nextVertex]=dist+val;//비용 갱신
					pq.add(new info(nextVertex, dist+val));//그리고 갱신된 정점을 다시 pq에 집어넣기
				}
			}
		}
		for(int i =1; i<=N;i++) {
			if(D[i]==2147483647)System.out.println("INF");
			else System.out.println(D[i]);
		}
	}
}