백준 1753 : 최단경로

23450 단어 백준백준

문제

방향그래프가 주어지면 주어진 시작점에서 다른 모든 정점으로의 최단 경로를 구하는 프로그램을 작성하시오. 단, 모든 간선의 가중치는 10 이하의 자연수이다.

입력
첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1≤V≤20,000, 1≤E≤300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1≤K≤V)가 주어진다. 셋째 줄부터 E개의 줄에 걸쳐 각 간선을 나타내는 세 개의 정수 (u, v, w)가 순서대로 주어진다. 이는 u에서 v로 가는 가중치 w인 간선이 존재한다는 뜻이다. u와 v는 서로 다르며 w는 10 이하의 자연수이다. 서로 다른 두 정점 사이에 여러 개의 간선이 존재할 수도 있음에 유의한다.

출력
첫째 줄부터 V개의 줄에 걸쳐, i번째 줄에 i번 정점으로의 최단 경로의 경로값을 출력한다. 시작점 자신은 0으로 출력하고, 경로가 존재하지 않는 경우에는 INF를 출력하면 된다
BOJ1753

접근

최단경로 알고리즘으로 유명한 다익스트라 알고리즘을 짜는 문제였다. 옛날에 관련된 프로젝트를 진행해본적이 있어 조금 찾아보니 기억이 났다.
다익스트라 알고리즘은 시작 노드로부터 나머지 노드까지의 최단경로를 찾는 알고리즘으로, 가중치 그래프에서 사용된다. 주요 과정은 이러하다.
1. dist 배열을 만들고 최대값으로 초기화한다.(시작점부터 i노드까지의 최단경로를 저장할 배열)
2. 시작점의 dist값을 0으로 설정하고, 시작점과 연결된 노드의 dist를 두 노드 사이의 거리로 설정한다.
3. 방문하지 않은 노드 중 dist값이 최소인 노드를 찾는다.
4. 해당 노드를 방문하고, 이 노드의 dist값이 직전 노드의 dist값 + 가중치의 값보다 크다면 이 값으로 설정한다.
5. 모든 노드를 방문할때까지 반복한다.

단순히 그래프만 놓고 해당 알고리즘을 실행했을때, 3번 과정에서 시간복잡도가 너무 커지므로, 우선순위 큐를 이용하여 다익스트라 알고리즘을 구현하였다.

코드 구현을 하고나서 다른 사람 코드를 봤는데, 내가 생각한 방식은 연결리스트의 인자를 연결리스트로 설정하여 가중치 그래프를 구현하였지만, 연결리스트의 배열로 설정한 코드를 보니 훨씬 더 보기좋았던것 같다.

코드

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


public class Main {
	public static class Edge implements Comparable<Edge> {
		public int v;
		public int Weight;
		
		public Edge(int x, int y) {
			this.v = x;
			this.Weight = y;
		}

		@Override
		public int compareTo(Edge o) {
			return this.Weight - o.Weight;
		}
	}

	public static void main(String[] args) throws IOException {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		String str = bf.readLine();
		StringTokenizer st = new StringTokenizer(str);
		int v = Integer.parseInt(st.nextToken());
		int e = Integer.parseInt(st.nextToken());
		int k = Integer.parseInt(bf.readLine());
		
		ArrayList<ArrayList<Edge>> graph = new ArrayList<>();
		for(int i = 0; i <= v; i++)
			graph.add(new ArrayList<Edge>());
		
		for(int i = 0; i<e; i++) {
			str = bf.readLine();
			st = new StringTokenizer(str);
			int a = Integer.parseInt(st.nextToken());
			int b = Integer.parseInt(st.nextToken());
			int c = Integer.parseInt(st.nextToken());
			
			graph.get(a).add(new Edge(b, c));
		}
		
		int [] dist = new int[v+1];
		boolean [] check = new boolean[v+1];
		
		Arrays.fill(dist, Integer.MAX_VALUE);
			
		PriorityQueue <Edge> pq = new PriorityQueue<Edge>();
		dist[k] = 0;
		pq.add(new Edge(k, 0));
		
		while(!pq.isEmpty()) {
			Edge now = pq.poll();
			int des = now.v;
			if(check[des])
				continue;
			
			check[des] = true;
			for(int i = 0; i < graph.get(des).size(); i++) {
				if(dist[graph.get(des).get(i).v] >= dist[des] + graph.get(des).get(i).Weight) {
					dist[graph.get(des).get(i).v] = dist[des] + graph.get(des).get(i).Weight;
					pq.add(new Edge(graph.get(des).get(i).v, dist[graph.get(des).get(i).v]));
				}
			}	
		}
		for(int i = 1; i <= v; i++) {
			if(dist[i] == Integer.MAX_VALUE)
				System.out.println("INF");
			else
				System.out.println(dist[i]);
		}
	}
}

좋은 웹페이지 즐겨찾기