티스토리 뷰

728x90

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

 

1238번: 파티

첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 10,000), X가 공백으로 구분되어 입력된다. 두 번째 줄부터 M+1번째 줄까지 i번째 도로의 시작점, 끝점, 그리고 이 도로를 지나는데 필요한 소요시간 Ti가 들어

www.acmicpc.net

 

문제

N개의 숫자로 구분된 각각의 마을에 한 명의 학생이 살고 있다.

어느 날 이 N명의 학생이 X (1 ≤ X ≤ N)번 마을에 모여서 파티를 벌이기로 했다. 이 마을 사이에는 총 M개의 단방향 도로들이 있고 i번째 길을 지나는데 Ti(1 ≤ Ti ≤ 100)의 시간을 소비한다.

각각의 학생들은 파티에 참석하기 위해 걸어가서 다시 그들의 마을로 돌아와야 한다. 하지만 이 학생들은 워낙 게을러서 최단 시간에 오고 가기를 원한다.

이 도로들은 단방향이기 때문에 아마 그들이 오고 가는 길이 다를지도 모른다. N명의 학생들 중 오고 가는데 가장 많은 시간을 소비하는 학생은 누구일지 구하여라.

입력

첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 10,000), X가 공백으로 구분되어 입력된다. 두 번째 줄부터 M+1번째 줄까지 i번째 도로의 시작점, 끝점, 그리고 이 도로를 지나는데 필요한 소요시간 Ti가 들어온다. 시작점과 끝점이 같은 도로는 없으며, 시작점과 한 도시 A에서 다른 도시 B로 가는 도로의 개수는 최대 1개이다.

모든 학생들은 집에서 X에 갈수 있고, X에서 집으로 돌아올 수 있는 데이터만 입력으로 주어진다.

출력

첫 번째 줄에 N명의 학생들 중 오고 가는데 가장 오래 걸리는 학생의 소요시간을 출력한다.

 

 

 

 

다익스트라 알고리즘을 사용하는 대표적인 문제 중 하나다.

일반적인 다익스트라 알고리즘을 사용하면 한 정점에서 모든 정점으로 가는 최단거리를 구할 수 있지만,

이번 문제에서는 특정 마을에 오고 가는 왕복 거리를 구해야 하고, 오고 가는 길이 다를 수 있다.

즉, 한 정점에서 모든 정점으로, 모든 정점에서 한 정점으로 가는 최단거리를 구해야 한다.

 

N의 최대가 1000이기 때문에 플로이드 워셜을 통해 구한다면 O(N^3)의 시간이 들어 시간초과가 날 것이다.

모든 정점에서 한 정점으로 가는 최단거리를 구하기 위해서는

문제의 입력을 반대로 입력한 배열을 만들어

이 배열에 대해 다익스트라 알고리즘을 적용하면 구할 수 있다.

 

즉,

한 정점에서 모든 정점으로 가는 최단 거리-> 일반적인 다익스트라

모든 정점에서 한 정점으로 가는 최단 거리-> 배열의 입력을 반대로 한 다익스트라

 

이렇게 두번의 다익스트라 알고리즘을 통해 문제를 풀 수 있다.

이 문제는 배열의 입력을 반대로 하는 것을 생각해내는 게 핵심인 것 같다.

 

 

import java.util.*;
import java.io.*;

public class Main {
	static int N, M, X;
	static int INF = 100001;

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		X = Integer.parseInt(st.nextToken());
		
		ArrayList<int[]> list[] = new ArrayList[N + 1];
		ArrayList<int[]> reverse[] = new ArrayList[N + 1];
		
		for(int i=1;i<=N;i++) {
			list[i] = new ArrayList<>();
			reverse[i] = new ArrayList<>();
		}
		
		for(int i=0;i<M;i++) {
			st = new StringTokenizer(br.readLine());
			int start = Integer.parseInt(st.nextToken());
			int end = Integer.parseInt(st.nextToken());
			int cost = Integer.parseInt(st.nextToken());
			
			list[start].add(new int[] {end, cost});
			reverse[end].add(new int[] {start, cost});
		}
		
		int result1[] = dijkstra(list);
		int result2[] = dijkstra(reverse);
		
		int max = result1[1] + result2[1];
		for(int i=2;i<=N;i++)
			max = Math.max(max, result1[i] + result2[i]);
		
		System.out.println(max);
	}
	
	static int[] dijkstra(ArrayList<int[]> list[]) {
		PriorityQueue<int[]> q = new PriorityQueue<>((o1, o2) -> o1[1] - o2[1]);
		
		boolean visit[] = new boolean[N + 1];
		int result[] = new int[N + 1];
		Arrays.fill(result, INF);
		
		q.offer(new int[] {X, 0});
		result[X] = 0;
		
		while(!q.isEmpty()) {
			int idx = q.poll()[0];

			if(!visit[idx]) {
				visit[idx] = true;
				for(int[] temp : list[idx]) {
					if(!visit[temp[0]] && result[temp[0]] > result[idx] + temp[1]) {
						result[temp[0]] = result[idx] + temp[1];
						q.offer(new int[] {temp[0], result[temp[0]]});
					}
				}
			}
		}
		
		return result;
	}

}
728x90
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함