백준 9370

旅人·2023년 3월 19일
0

문제


Code

package test;

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

public class P9370 {
	static class Node implements Comparable<Node> {
		int end;
		int weight; // 시작 지점부터 해당 노드까지의 총 길이 저장

		Node(int end, int weight) {
			this.end = end;
			this.weight = weight;
		}

		@Override
		public int compareTo(Node o) {
			return weight - o.weight;
		}
	}
	static final int INF = 50000000; // 경로 존재하지 않음
	static ArrayList<ArrayList<Node>> list; // 인접 리스트
	static boolean[] visited;
	static int[] dist; // dist[i] : 시작지점부터 i번 노드까지 최단거리
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		StringBuilder sb = new StringBuilder();
		StringTokenizer st;

		int T = Integer.parseInt(br.readLine());

		for(int i = 0; i < T; i++) {
			st = new StringTokenizer(br.readLine(), " ");
			int n = Integer.parseInt(st.nextToken());
			int m = Integer.parseInt(st.nextToken());
			int t = Integer.parseInt(st.nextToken());

			list = new ArrayList<>();
			for(int j = 0; j <= n; j++) {
				list.add(new ArrayList<>());
			}
			dist = new int[n + 1];
			visited = new boolean[n + 1];

			st = new StringTokenizer(br.readLine(), " ");
			int s = Integer.parseInt(st.nextToken());
			int g = Integer.parseInt(st.nextToken());
			int h = Integer.parseInt(st.nextToken());

			for(int j = 0; j < m; j++) {
				st = new StringTokenizer(br.readLine(), " ");
				int a = Integer.parseInt(st.nextToken());
				int b = Integer.parseInt(st.nextToken());
				int d = Integer.parseInt(st.nextToken());

				list.get(a).add(new Node(b, d));
				list.get(b).add(new Node(a, d));
			}
			
            // 출력을 각 줄 마다 오름 차순으로 해야하므로 우선순위 큐 사용
			PriorityQueue<Integer> pq = new PriorityQueue<>();
            
            // 목적지 후보
			int[] destination = new int[t + 1];
			for(int j = 1; j <= t; j++) {
				destination[j] = Integer.parseInt(br.readLine());
			}
			for(int d : destination) {
				int commonDistance = dijkstra(g, h);
				int path1 = dijkstra(s, g) + commonDistance + dijkstra(h, d);
				int path2 = dijkstra(s, h) + commonDistance + dijkstra(g, d);
				int path3 = dijkstra(s, d);

				if(path3 != INF) {
                	// g와 h를 거치는 길이 실제로 최단 거리여야 한다.
					if(Math.min(path1, path2) == path3) {
						pq.add(d);
					}
				}
			}
			while(!pq.isEmpty()) {
            	// 가능한 목적지 후보 오름차순 출력
				sb.append(pq.poll()).append(" ");
			}
            // 다음 테스트 케이스
			sb.append('\n');			
		}
		bw.write(sb.toString());

		br.close();
		bw.flush();
		bw.close();
	}
	private static int dijkstra(int start, int end) {
		Arrays.fill(dist, INF); 
		Arrays.fill(visited, false);
		// bfs로 탐색할 자식 노드 저장할 우선순위 큐
		// 총 거리가 적을수록 우선순위 높다
		PriorityQueue<Node> pque = new PriorityQueue<>();
		// 탐색노드, start에서 시작하고, 아직 총 거리는 0
		pque.add(new Node(start, 0)); 
		dist[start] = 0;

		while(!pque.isEmpty()) {
			Node currentNode = pque.poll();
			int current = currentNode.end;

			if(visited[current]) {
				continue;
			}
			visited[current] = true;

			for(Node next : list.get(current)) {
				// 최단거리 갱신
				if(dist[next.end] > dist[current] + next.weight) {
					dist[next.end] = dist[current] + next.weight;
					pque.add(new Node(next.end, dist[next.end]));
				}
			}

		}
		return dist[end];
	}

}
profile
一期一会

0개의 댓글