
다익스트라 알고리즘은 그래프에서 최단 거리를 구하는 알고리즘
완성된 배열 = 시작 노드부터 i노드 까지 최단 거릿값 저장
출발 노드와 이외의 모든 노드 간의 최단거리를 표현한다.


// 모든 정점까지 거리 구하기
public class Main {
	static final int INF = 987654321;
	static final int MAX_N = 10;
	static int N,E;
	static int[][] Graph = new int[MAX_N][MAX_N];
	static int[] Dist = new int[MAX_N];
	
	static void dijkstra(int src) {
    	// 우선순위 큐. 람다로 표현 두개값을 비교할때 첫번째 인덱스로 표현하란 의미
		PriorityQueue<int[]> pq = new PriorityQueue<>((a,b)->a[0]-b[0]);
		boolean[] visited = new boolean[MAX_N];
		for(int i=0; i<N; i++) Dist[i] = INF;
		Dist[src] = 0;
		pq.add(new int[] {0,src});
		
		while(!pq.isEmpty()) {
			int[] curr = pq.poll();
			int u = curr[1];
			if(visited[u]) continue; // 스킵
			
			visited[u] = true;
			for(int v=0; v<N; v++) {
				if(Dist[v] > Dist[u] + Graph[u][v]) {
					Dist[v] = Dist[u]+Graph[u][v];
					pq.add(new int[] {Dist[v],v});
				}
			}
		}
	}
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		N = sc.nextInt();
		E = sc.nextInt();
		for(int i = 0; i<N; i++) {
			for(int j = 0; j<N; j++) {
				if(i==j) Graph[i][j] = 0;
				else Graph[i][j] = INF; // 의미상 무한
			}
		}
		for(int i=0; i<E; i++) {
			int u = sc.nextInt();
			int v = sc.nextInt();
			int cost = sc.nextInt();
			Graph[u][v] = Graph[v][u] = cost; // 방향성이 없는걸 의미
		}
		dijkstra(0);
		for(int i=0; i<N; i++)
			System.out.print(Dist[i] + " "); // 0 50 30 50 60 90
	}
} // 경로가 필요한 경우
public class Main {
	static final int INF = 987654321;
	static final int MAX_N = 10;
	static int N,E;
	static int[][] Graph = new int[MAX_N][MAX_N];
	static int[] Dist = new int[MAX_N];
	static int[] Prev = new int[MAX_N];
	static void dijkstra(int src) {
		PriorityQueue<int[]> pq = new PriorityQueue<>((a,b)->a[0]-b[0]);
		boolean[] visited = new boolean[MAX_N];
		for(int i=0; i<N; i++) {Prev[i] = -1; Dist[i] = INF;}
		Dist[src] = 0;
		pq.add(new int[] {0,src});
		
		while(!pq.isEmpty()) {
			int[] curr = pq.poll();
			int u = curr[1];
			if(visited[u]) continue;
			visited[u] = true;
			for(int v=0; v<N; v++) {
				if(Dist[v] > Dist[u] + Graph[u][v]) {
					Prev[v] = u; // 정점 바로 전 노드는 u이다 -> 이전노드 저장
					Dist[v] = Dist[u]+Graph[u][v]; // 최소비용 저장
					pq.add(new int[] {Dist[v],v});
				}
			}
		}
	}
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		N = sc.nextInt();
		E = sc.nextInt();
		for(int i = 0; i<N; i++) {
			for(int j = 0; j<N; j++) {
				if(i==j) Graph[i][j] = 0;
				else Graph[i][j] = INF; // 의미상 무한
			}
		}
		for(int i=0; i<E; i++) {
			int u = sc.nextInt();
			int v = sc.nextInt();
			int cost = sc.nextInt();
			Graph[u][v] = Graph[v][u] = cost; // 방향성이 없는걸 의미
		}
		dijkstra(0);
		int curr = 5;
		while(curr != -1) {
			System.out.print(curr + " < ");
			curr = Prev[curr];
		}
	} // 5 < 4 < 3 < 2 < 0 <// 특정 도착점까지 거리 구하기(2)
public class Main {
	static final int INF = 987654321;
	static final int MAX_N = 10;
	static int N,E;
	static int[][] Graph = new int[MAX_N][MAX_N];
	static int[] Dist = new int[MAX_N];
	static int[] Prev = new int[MAX_N];
	
	static int dijkstra(int src, int dst) { // dst - 도착점. 최단 거리 비용만 반환하기 위해 리턴타입을 int로 변경
		PriorityQueue<int[]> pq = new PriorityQueue<>((a,b)->a[0]-b[0]);
		boolean[] visited = new boolean[MAX_N];
		for(int i=0; i<N; i++) {Prev[i] = -1; Dist[i] = INF;}
		Dist[src] = 0;
		pq.add(new int[] {0,src});
		
		while(!pq.isEmpty()) {
			int[] curr = pq.poll();
			int u = curr[1];
			if(u==dst) return curr[0]; // 더이상 진행하지 않음. 비용 바로 반환하고 종료
			if(visited[u]) continue;
			visited[u] = true;
			for(int v=0; v<N; v++) {
				if(Dist[v] > Dist[u] + Graph[u][v]) {
					Dist[v] = Dist[u]+Graph[u][v]; // 최소비용 저장
					pq.add(new int[] {Dist[v],v});
				}
			}
		}
		return INF; // 무한을 반환함으로써 해당 도착점으로는 갈 수 없다는걸 표현
	}
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		N = sc.nextInt();
		E = sc.nextInt();
		for(int i = 0; i<N; i++) {
			for(int j = 0; j<N; j++) {
				if(i==j) Graph[i][j] = 0;
				else Graph[i][j] = INF; // 의미상 무한
			}
		}
		for(int i=0; i<E; i++) {
			int u = sc.nextInt();
			int v = sc.nextInt();
			int cost = sc.nextInt();
			Graph[u][v] = Graph[v][u] = cost; // 방향성이 없는걸 의미
		}
		for(int i=0; i<N; i++)
			System.out.println(dijkstra(0,i));
	}
} // 0 50 30 50 60 90