백준

[백준_1939번] 중량제한

빙수빈수 2022. 1. 14. 13:41

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

 

1939번: 중량제한

첫째 줄에 N, M(1 ≤ M ≤ 100,000)이 주어진다. 다음 M개의 줄에는 다리에 대한 정보를 나타내는 세 정수 A, B(1 ≤ A, B ≤ N), C(1 ≤ C ≤ 1,000,000,000)가 주어진다. 이는 A번 섬과 B번 섬 사이에 중량제한이

www.acmicpc.net

[문제]

 N(2 ≤ N ≤ 10,000)개의 섬으로 이루어진 나라가 있다. 이들 중 몇 개의 섬 사이에는 다리가 설치되어 있어서 차들이 다닐 수 있다.

 영식 중공업에서는 두 개의 섬에 공장을 세워 두고 물품을 생산하는 일을 하고 있다. 물품을 생산하다 보면 공장에서 다른 공장으로 생산 중이던 물품을 수송해야 할 일이 생기곤 한다. 그런데 각각의 다리마다 중량제한이 있기 때문에 무턱대고 물품을 옮길 순 없다. 만약 중량제한을 초과하는 양의 물품이 다리를 지나게 되면 다리가 무너지게 된다.

 한 번의 이동에서 옮길 수 있는 물품들의 중량의 최댓값을 구하는 프로그램을 작성하시오.

 

[입력 조건]

 첫째 줄에 N, M(1 ≤ M ≤ 100,000)이 주어진다. 다음 M개의 줄에는 다리에 대한 정보를 나타내는 세 정수 A, B(1 ≤ A, B ≤ N), C(1 ≤ C ≤ 1,000,000,000)가 주어진다. 이는 A번 섬과 B번 섬 사이에 중량제한이 C인 다리가 존재한다는 의미이다. 서로 같은 두 섬 사이에 여러 개의 다리가 있을 수도 있으며, 모든 다리는 양방향이다. 마지막 줄에는 공장이 위치해 있는 섬의 번호를 나타내는 서로 다른 두 정수가 주어진다. 공장이 있는 두 섬을 연결하는 경로는 항상 존재하는 데이터만 입력으로 주어진다.

 

[코드]

import java.util.*;

class Point_1939 {
	int island, weight;
	
	public Point_1939(int island, int weight) {
		this.island=island;
		this.weight=weight;
	}
}
public class BaekJoon_1939 {
	static int n,m;
	static boolean[] visited;
	static ArrayList<ArrayList<Point_1939>> graph=new ArrayList<>();
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		m=sc.nextInt();
		
		for(int i=0;i<=n;i++)
			graph.add(new ArrayList<>());
		
		int max=0;
		for(int i=0;i<m;i++) {
			int a=sc.nextInt();
			int b=sc.nextInt();
			int w=sc.nextInt();
			
			max=Math.max(max, w); // 이분탐색의 right가 될 값 구하기(중량중 최댓 값)
			graph.get(a).add(new Point_1939(b,w));
			graph.get(b).add(new Point_1939(a,w));
		}
		
		int start=sc.nextInt(); // 시작 위치
		int end=sc.nextInt(); // 도착 위치
		
		// 이분탐색
		int left=0;
		int right=max;
		
		while(left<=right) {
			int mid=(left+right)/2;
			visited=new boolean[n+1];
			
			// mid 중량으로 start에서 end까지 이동할 수 있다면 left 증가 -> 중량이 더 무거워 짐
			if(Cross_Bridge(start,end,mid)) 
				left=mid+1;
			// mid 중량으로 start에서 end까지 이동할 수 없다면 right 감소 -> 중량이 더 가벼워 짐
			else
				right=mid-1;
		}
		
		System.out.println(right);
	}

	// start에서 end까지 이동할 수 있는지 확인하는 함수
	static boolean Cross_Bridge(int start, int end, int mid) {
		Queue<Integer> q=new LinkedList<>();
		q.add(start);
		visited[start]=true;
		
		while(!q.isEmpty()) {
			int now=q.poll();
			
			if(now==end) // end에 도달했다면 성공
				return true;
			
			for(Point_1939 next:graph.get(now)) {
				// 다음 섬이 아직 방문하지 않았으며 mid 중량이 다리를 건널수 있다면
				if(!visited[next.island]&&mid<=next.weight) {
					visited[next.island]=true; // 방문 처리
					q.offer(next.island); // 큐에 삽입
				}
			}
		}
		return false;
	}
}

 

[고찰]

 이번 문제는 이분 탐색과 BFS를 함께 사용해야 하는 문제였다. 이분 탐색을 사용해 한 번의 이동에서 옮길 수 있는 물품들의 중량의 최댓값을 설정하고, 해당 중량으로 start 지점에서 end 지점까지 이동할 수 있는지의 여부를 BFS 알고리즘으로 구성해야 정답 처리를 받을 수 있었다.

 이렇게 이분 탐색과 BFS를 접목한 문제는 처음 풀어봐서 그런지 코드를 짜면서 이런 방식으로도 문제를 해결할 수 있구나란 생각을 했다. 

'백준' 카테고리의 다른 글

[백준_1202번] 보석 도둑  (0) 2022.01.19
[백준_19238번] 스타트 택시  (0) 2022.01.14
[백준_9342번] 염색체  (0) 2022.01.11
[백준_1253번] 좋다  (0) 2022.01.11
[백준_1976번] 여행가자  (0) 2022.01.11