Search
Duplicate

[Python] BOJ 1939

태그
BFS
이진 탐색
1 more property
이분탐색 말고 BFS, 다익스트라 만으로도 풀 수 있다고 한다. 다시 풀어보자!

문제

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)가 주어진다.
마지막 줄에는 공장이 위치해 있는 섬의 번호를 나타내는 서로 다른 두 정수가 주어진다.
구해야 하는 값이 중량 C인 상황에서 C의 범위가 1 ≤ ≤ 1,000,000,000 의 큰 범위이다. 따라서 다익스트라, BFS 등을 통한 그래프 알고리즘만으로 문제를 해결하지 못하고 C의 값을 찾는 경우라면 Log(N) 알고리즘을 사용해야 한다.

풀이

기본 알고리즘
#Loop 1. 이분탐색을 통해 특정 다리의 무게 C 를 설정한다. 2. BFS로 그래프를 탐색하며 C 이상의 다리를 사용해서 목적지에 도착할 수 있는지 검사한다 3. 목적지에 도착할 수 있으면 다리의 무게 C를 증가시키고 도착할 수 없다면 다리의 무게 C를 감소시킨다.
Python
복사
bfs 함수 (그래프 탐색) - c = 이분탐색을 통해 정한 다리의 무게값
def bfs(c): q = deque() visit = [False] * (N + 1) q.append(f1) visit[f1] = True while q: cur = q.popleft() if visit[f2] == True: # 목적지에 갈 수 있으면 탐색 중단해 성능 향상 return True for y, weight in arr[cur]: if visit[y] == 0 and weight >= c: # 다리의 하중이 c 이상인 경우에만 탐색 진행 visit[y] = True q.append(y) return visit[f2]
Python
복사
입력
N, M = map(int, input().split()) # 섬의 개수, 다리의 개수 arr = [[] for _ in range(N + 1)] left = 1000000000 # 이진탐색 left값 right = 1 # 이진탐색 right 값 for _ in range(M): a, b, c = map(int, input().split()) arr[a].append((b,c)) arr[b].append((a,c)) left = min(left, c) right = max(right, c) f1, f2 = map(int, input().split()) # 섬의 개수, 다리의 개수
Python
복사
Main 함수 동작
result = 0 while left <= right: mid = (left + right) // 2 if bfs(mid): # 목적지에 갈 수 있음 left = mid + 1 # 무게 증가 result = mid else: right = mid - 1 print(result)
Python
복사

중요

1.
Python의 List 만으로도 queue 동작을 구현할 수 있지만 deque에 비해 성능이 나쁘다. deque 사용법을 익혀서 사용하자!
from collections import deque q = deque()
Python
복사