알고리즘

[백준] 특정한 최단 경로 1504 - java

minkang 2021. 7. 12. 14:00

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

 

1504번: 특정한 최단 경로

첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄에 걸쳐서 세 개의 정수 a, b, c가 주어지는데, a번 정점에서 b번 정점까지 양방향 길이 존

www.acmicpc.net

public class 특정한최단경로 {
	static class Node implements Comparable<Node>{
		int no;
		int weight;
		public Node(int no, int weight) {
			super();
			this.no = no;
			this.weight = weight;
		}
		
		public int compareTo(Node o) {
			return Integer.compare(this.weight, o.weight);
		}
	}
	
	static int adj[][];
	static int N,M;
	static final int INF = 200000000;
	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());
		
		adj = new int[N+1][N+1];
		for(int i=0; i<M; i++) {
			st = new StringTokenizer(br.readLine());
			int a = Integer.parseInt(st.nextToken());
			int b = Integer.parseInt(st.nextToken());
			int w = Integer.parseInt(st.nextToken());
			adj[a][b] = w;
			adj[b][a] = w;
		}
		
		st = new StringTokenizer(br.readLine());
		int v1 = Integer.parseInt(st.nextToken());
		int v2 = Integer.parseInt(st.nextToken());

		int sum = 0;
		sum += dijkstra(1, v1);
		sum += dijkstra(v1, v2);
		sum += dijkstra(v2, N);
		int answer = sum;

		sum = 0;
		sum += dijkstra(1, v2);
		sum += dijkstra(v2, v1);
		sum += dijkstra(v1, N);
		answer = Math.min(answer, sum);
		
		if(answer >= INF) {
			System.out.println(-1);
		}
		else {
			System.out.println(answer);
		}
	}
	
	private static boolean isCheck(int sum) {
		if(sum ==Integer.MAX_VALUE) {
			return true;
		}
		return false;
	}

	static int dijkstra(int start, int end) {
		
		PriorityQueue<Node> pq = new PriorityQueue<Node>();
		pq.offer(new Node(start, 0));
		
		int dist[] = new int[N+1];
		boolean visited[] = new boolean[N+1];
		Arrays.fill(dist, INF);
		dist[start] = 0;
		
		while(!pq.isEmpty()) {
			Node cur = pq.poll();
			if(visited[cur.no] == true) continue;
			visited[cur.no] = true;

			for(int i=1; i<=N; i++) {
				if(!visited[i] && adj[cur.no][i] != 0 && dist[i] > adj[cur.no][i] + cur.weight) {
					dist[i] = adj[cur.no][i] + cur.weight;
					pq.offer(new Node(i, adj[cur.no][i] + cur.weight));
				}
			}
		}
		return dist[end];
	}
}

두 점을 거쳐가는 최단경로를 구하는 문제입니다.

1) 1 -> v1 -> v2 -> N

2) 1 -> v2 -> v1 -> N

위와 같이 2자기 방법에 대해 최단 경로를 구해서 최솟값으로 출력하면 됩니다.

 

여기서 INF 값은 최대로 거리가 1000, 간선의 갯수가 200000이므로 1000*200000 +1로 설정했습니다.