본문 바로가기
Algorithm/BOJ

[백준] 1753번 최단경로 자바

by YOONAYEON 2021. 12. 7.
문제 (골드5, 다익스트라 알고리즘)

 

 

1753번: 최단경로

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

www.acmicpc.net

 

 

문제풀이

 

처음에 다익스트라 알고리즘인 줄 모르고 DFS로 풀었다.

정점과 가중치 값을 ' , '로 연결하여 ArrayList에 String값을 담아서 도착 정점까지의 가중치합을 합하여 weight배열에 담아줬었다.

도착정점까지 가는 모든 가중치합을 비교하며 weight배열을 갱신하고 마지막에 출력해줬다.

 

이렇게...

public class Main {

	static int[] weight;
	static ArrayList<String>[] list;
	static boolean check;
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int V = sc.nextInt();
		int E = sc.nextInt();
		int startV = sc.nextInt();
		
		weight = new int[V+1];
		list = new ArrayList[V+1];
		for(int i = 1; i < V+1; i++)
			list[i] = new ArrayList<String>();
		
		for(int i = 0; i < E; i++) {
			int u = sc.nextInt();
			int v = sc.nextInt();
			int w = sc.nextInt();
			String temp = String.valueOf(v) + "," + String.valueOf(w);
			list[u].add(temp);
		}
		
		for(int i = 1; i <= V; i++) {
			if(i != startV) {
				check = false;
				DFS(startV, i, 0);
				if(check == false)
					weight[i] = -1;
			}
		}
		
		for(int i = 1; i <= V; i++) {
			if(weight[i] == -1)
				System.out.println("INF");
			else
				System.out.println(weight[i]);
		}
		
		sc.close();
		return;
	}
	
	static void DFS(int start, int destination, int total) {
		if(start == destination) {
			if(weight[destination] == 0 || total < weight[destination])
				weight[destination] = total;
			check = true;
			return;
		}
		
		for(String str : list[start]) {
			String[] s = str.split(",");
			int v = Integer.parseInt(s[0]);
			int w = Integer.parseInt(s[1]);
			DFS(v, destination, total+w);
		}
	}
}

 

 

테스트케이스는 맞았지만 제출해보면

 

...^^,,

 

그래서 인터넷에 찾아보니 다익스트라 알고리즘이었고, 단순히 배열로 구현할 수는 있지만 배열 + 우선순위 큐를 이용하여 구현해야 시간 효율성이 훨씬 뛰어났다.

 

다익스트라 알고리즘이란 하나의 정점에서 다른 점들로 가는 최단경로(거리)를 구할 때 사용하는 알고리즘이다. (단, 음의 가중치가 없어야 함)

1. 정점의 최단거리 값을 담을 배열을 하나 생성

2. 자기자신은 0으로, 그 외에는 INF값으로 초기화

3. 시작 정점(자신)을 방문 했을 때, 연결가능한 다른 정점 값들 갱신

4. 시작정점에서 뻗어가는 가장 작은 가중치를 가진 정점 방문

5. 방문정점의 현재 배열값현재정점 배열값+방문정점과 연결된 가중치값 중 작은 값으로 업데이트 

 

참고: https://jellyinghead.tistory.com/78

 

 

소스코드

 

import java.util.ArrayList;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Scanner;

public class b_1753 {
	
	static ArrayList<Node>[] list;
	static int dist[];
	static boolean[] visited;
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int V = sc.nextInt();
		int E = sc.nextInt();
		int startV = sc.nextInt();
		
		visited = new boolean[V+1];
		list = new ArrayList[V+1];
		dist = new int[V+1];
		
		Arrays.fill(dist, -1); 	//dist배열 -1로 채우기
		dist[startV] = 0;		// 시작 정점
		
		for(int i = 1; i <= V; i++)
			list[i] = new ArrayList<>();
		
		for(int i = 0; i < E; i++) {
			int u = sc.nextInt();
			int v = sc.nextInt();
			int w = sc.nextInt();
			list[u].add(new Node(v, w));
		}
		
		Dijkstra(startV);
		for(int i = 1; i <= V; i++) {
			if(dist[i] == -1)
				System.out.println("INF");
			else
				System.out.println(dist[i]);
		}
		
	}
	
	static void Dijkstra(int start) {
		PriorityQueue<Node> q = new PriorityQueue<>();
		
		q.add(new Node(start, 0)); //값 추가
		
		while(!q.isEmpty()) {
			Node now = q.poll();	// 큐의 첫번째 값 반환후 제거
			if(visited[now.node])
				continue;
			
			visited[now.node] = true;
			for(Node next : list[now.node]) {
				if(dist[next.node]==-1 || dist[next.node] > dist[now.node]+next.weight) {
					dist[next.node] = dist[now.node] + next.weight;
					q.add(new Node(next.node, dist[next.node]));
				}
			}
		}
	}
	
	private static class Node implements Comparable<Node>{
		int node, weight;
		
		Node(int n, int w){
			this.node = n;
			this.weight = w;
		}
		
		public int compareTo(Node n) {
			return weight - n.weight;
		}
	}

}

 

'Algorithm > BOJ' 카테고리의 다른 글

[백준] 1987번 알파벳 자바  (0) 2022.01.03
[백준] 11399번 ATM 자바  (0) 2022.01.03
[백준] 9251번 LCS 자바  (0) 2021.11.29
[백준] 17413번 단어 뒤집기2 자바  (0) 2021.11.27
[백준] 1260번 DFS와 BFS 자바  (0) 2021.11.17