( •̀ ω •́ )✧
BOJ 16118. 달빛 여우 (Python) / 다익스트라 본문
🔎 BOJ 16118. 달빛 여우 (Gold 1)
https://www.acmicpc.net/problem/16118
16118번: 달빛 여우
첫 줄에 나무 그루터기의 개수와 오솔길의 개수를 의미하는 정수 N, M(2 ≤ N ≤ 4,000, 1 ≤ M ≤ 100,000)이 주어진다. 두 번째 줄부터 M개의 줄에 걸쳐 각 줄에 세 개의 정수 a, b, d(1 ≤ a, b ≤ N, a ≠ b
www.acmicpc.net
💡 SOL
import sys
from heapq import heappush, heappop
input = sys.stdin.readline
N, M = map(int, input().split())
arr = [[] for _ in range(N + 1)]
for _ in range(M):
a, b, d = map(int, input().split())
arr[a].append((b, d))
arr[b].append((a, d))
# 여우 (정속)
v_fox = [float('inf')] * (N + 1)
v_fox[1] = 0
q = [(0, 1)] # (cost, node)
while q:
cost, s = heappop(q)
if cost > v_fox[s]: continue
for e, d in arr[s]:
new_cost = cost + d
if v_fox[e] > new_cost:
heappush(q, (new_cost, e))
v_fox[e] = new_cost
# 늑대 (변속)
v_wolf = [[float('inf'), float('inf')] for _ in range(N + 1)] # [False일때, True일때]
q = [(0, 1, True)] # (cost, node, t:가속/f:감속)
v_wolf[1][0] = 0
while q:
cost, s, fast = heappop(q)
if cost > v_wolf[s][not fast]: continue
for e, d in arr[s]:
if fast:
new_cost = cost + (d / 2)
else:
new_cost = cost + (d * 2)
if v_wolf[e][fast] > new_cost:
v_wolf[e][fast] = new_cost
heappush(q, (new_cost, e, not fast))
cnt = 0
for i in range(2, N + 1):
if v_fox[i] < min(v_wolf[i]):
cnt += 1
print(cnt)
💭 TIL
# 위 코드 중 일부 발췌
v_fox = [float('inf')] * (N + 1)
v_fox[1] = 0
q = [(0, 1)] # (cost, node)
while q:
cost, s = heappop(q)
# q에서 node를 꺼내 쓸 때 최신화된 visited(=v)에 저장된 가중치의 최소값으로 필터링해주면
# 똑같은 node를 여러 번 탐색하는 상황을 걸러낼 수 있다.
if cost > v_fox[s]: continue
for e, d in arr[s]:
new_cost = cost + d
if v_fox[e] > new_cost:
# 같은 node가 다른 가중치를 가지고 q에 여러 번 추가될 수 있음
heappush(q, (new_cost, e))
v_fox[e] = new_cost
시간 초과때문에 고생했던 문제라 기록해둔다. (여전히 pypy로는 통과 안 됨)
dfs/bfs, 다익스트라 문제 많이 풀었지만 이 문제 시간 초과때문에 효율성에 대해 많이 고민해보게 되었다. 오히려 좋아 ^^ㅠ..
현재 위치에서 가능한 다음 위치를 찾으며 탐색할 때,
예를 들어 가중치 10을 가지는 다음 노드 2
와 가중치 5를 가지는 다음 노드 2
가 q
에 순차적으로 들어온 상태라면
(최솟값을 찾는다는 가정 하에) 가중치 10인 노드 2
는 다음 현재 위치로 고려하지 않아도 된다.
어차피 가중치 5짜리 노드 2
를 탐색하면 되기 때문에!
따라서 현재 위치인 s
를 뽑았을 때, 최신화된 visited(=v)
에 저장된 가중치 값보다 크다면 그냥 pass 해버려도 좋다.
cost, s = heappop(q)
if cost > v_fox[s]: continue
해당 코드를 빼도 정답에 영향은 없지만 시간 제한이 중요한 문제에서는 필요하겠다..
가중치를 갖는 그래프 문제에서 범용적으로 써먹을 수 있을 것 같다.
'🤖 알고리즘' 카테고리의 다른 글
BOJ 18353. 병사 배치하기 (Silver 2) / 가장 긴 감소 수열 찾기 (0) | 2023.10.30 |
---|---|
BOJ 2110. 공유기 설치 (Gold 4) / 이분탐색 조건 설정 (0) | 2023.10.20 |
BOJ 1789. 수들의 합 (0) | 2023.08.10 |
BOJ 1456. 거의 소수 (0) | 2023.04.06 |
BOJ 2800. 괄호 제거 (0) | 2023.03.29 |
Comments