μ•Œκ³ λ¦¬μ¦˜/κ·Έλž˜ν”„

[λ°±μ€€ 1238 πŸ₯‡] νŒŒν‹°

1eehyunji 2023. 8. 15. 00:49

문제

N개의 숫자둜 κ΅¬λΆ„λœ 각각의 λ§ˆμ„μ— ν•œ λͺ…μ˜ 학생이 μ‚΄κ³  μžˆλ‹€.

μ–΄λŠ λ‚  이 Nλͺ…μ˜ 학생이 X (1 ≤ X ≤ N)번 λ§ˆμ„μ— λͺ¨μ—¬μ„œ νŒŒν‹°λ₯Ό 벌이기둜 ν–ˆλ‹€. 이 λ§ˆμ„ μ‚¬μ΄μ—λŠ” 총 M개의 단방ν–₯ λ„λ‘œλ“€μ΄ 있고 i번째 길을 μ§€λ‚˜λŠ”λ° Ti(1 ≤ Ti ≤ 100)의 μ‹œκ°„μ„ μ†ŒλΉ„ν•œλ‹€.

각각의 학생듀은 νŒŒν‹°μ— μ°Έμ„ν•˜κΈ° μœ„ν•΄ κ±Έμ–΄κ°€μ„œ λ‹€μ‹œ κ·Έλ“€μ˜ λ§ˆμ„λ‘œ λŒμ•„μ™€μ•Ό ν•œλ‹€. ν•˜μ§€λ§Œ 이 학생듀은 μ›Œλ‚™ κ²Œμ„λŸ¬μ„œ μ΅œλ‹¨ μ‹œκ°„μ— 였고 κ°€κΈ°λ₯Ό μ›ν•œλ‹€.

이 λ„λ‘œλ“€μ€ 단방ν–₯이기 λ•Œλ¬Έμ— μ•„λ§ˆ 그듀이 였고 κ°€λŠ” 길이 λ‹€λ₯Όμ§€λ„ λͺ¨λ₯Έλ‹€. Nλͺ…μ˜ 학생듀 쀑 였고 κ°€λŠ”λ° κ°€μž₯ λ§Žμ€ μ‹œκ°„μ„ μ†ŒλΉ„ν•˜λŠ” 학생은 λˆ„κ΅¬μΌμ§€ κ΅¬ν•˜μ—¬λΌ.

μž…λ ₯

첫째 쀄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 10,000), Xκ°€ 곡백으둜 κ΅¬λΆ„λ˜μ–΄ μž…λ ₯λœλ‹€. 두 번째 쀄뢀터 M+1번째 μ€„κΉŒμ§€ i번째 λ„λ‘œμ˜ μ‹œμž‘μ , 끝점, 그리고 이 λ„λ‘œλ₯Ό μ§€λ‚˜λŠ”λ° ν•„μš”ν•œ μ†Œμš”μ‹œκ°„ Tiκ°€ λ“€μ–΄μ˜¨λ‹€. μ‹œμž‘μ κ³Ό 끝점이 같은 λ„λ‘œλŠ” μ—†μœΌλ©°, μ‹œμž‘μ κ³Ό ν•œ λ„μ‹œ Aμ—μ„œ λ‹€λ₯Έ λ„μ‹œ B둜 κ°€λŠ” λ„λ‘œμ˜ κ°œμˆ˜λŠ” μ΅œλŒ€ 1κ°œμ΄λ‹€.

λͺ¨λ“  학생듀은 μ§‘μ—μ„œ X에 갈수 있고, Xμ—μ„œ μ§‘μœΌλ‘œ λŒμ•„μ˜¬ 수 μžˆλŠ” λ°μ΄ν„°λ§Œ μž…λ ₯으둜 μ£Όμ–΄μ§„λ‹€.

좜λ ₯

첫 번째 쀄에 Nλͺ…μ˜ 학생듀 쀑 였고 κ°€λŠ”λ° κ°€μž₯ 였래 κ±Έλ¦¬λŠ” ν•™μƒμ˜ μ†Œμš”μ‹œκ°„μ„ 좜λ ₯ν•œλ‹€.

λ¬Έμ œν’€μ΄

import sys
import heapq


n,m,x=map(int, sys.stdin.readline().split(' '))
path=[[] for _ in range(n+1)]
# μ—­λ°©ν–₯κ·Έλž˜ν”„
pathR=[[] for _ in range(n+1)]
for _ in range(m):
    s,e,t=map(int, sys.stdin.readline().split(' '))
    path[s].append((e,t))
    pathR[e].append((s,t))

# partyμ—μ„œ 각 λ§ˆμ„λ‘œ λŒμ•„κ°€λŠ” μ΅œλ‹¨ 경둜
fromParty=[1e9]*(n+1)
fromParty[x]=0

heap=[]
heapq.heappush(heap, (0,x))
while heap:
    time, cur = heapq.heappop(heap)
    # 이미 μ²˜λ¦¬λ˜μ–΄ μžˆλŠ” 지점이라면 즉, 이전에 κ³„μ‚°λœ μ΅œλ‹¨ κ²½λ‘œκ°€ ν˜„μž¬ 이 time 값보닀 μž‘μ•„μ„œ ν˜„μž¬ time을 κ°€μ§€κ³  더 이상 계산해 쀄 ν•„μš”κ°€ μ—†μŒ
    if time > fromParty[cur]:
        continue
    for nn,nt in path[cur]:
        if fromParty[nn]>time+nt:
            fromParty[nn]=time+nt
            heapq.heappush(heap, (time+nt, nn))

# 각 λ§ˆμ„μ—μ„œ party둜 κ°€λŠ” μ΅œλ‹¨ 경둜
toParty=[1e9]*(n+1)
toParty[x]=0
heapR=[]
heapq.heappush(heapR, (0,x))
while heapR:
    time, cur = heapq.heappop(heapR)
    # 이미 μ²˜λ¦¬λ˜μ–΄ μžˆλŠ” 지점이라면 즉, 이전에 κ³„μ‚°λœ μ΅œλ‹¨ κ²½λ‘œκ°€ ν˜„μž¬ 이 time 값보닀 μž‘μ•„μ„œ ν˜„μž¬ time을 κ°€μ§€κ³  더 이상 계산해 쀄 ν•„μš”κ°€ μ—†μŒ
    if time > toParty[cur]:
        continue
    for nn,nt in pathR[cur]:
        if toParty[nn]>time+nt:
            toParty[nn]=time+nt
            heapq.heappush(heapR, (time+nt, nn))

ans=-1e9
for i in range(1,n+1):
    ans=max(ans, toParty[i]+fromParty[i])

print(ans)
  • 각 n번째 λ§ˆμ„μ—μ„œ x번째 λ§ˆμ„λ‘œ κ°€λŠ” μ΅œλ‹¨ 경둜λ₯Ό κ΅¬ν•˜κ³  배열에 μ €μž₯ν•œλ‹€. (toParty)
  • x번째 λ§ˆμ„μ—μ„œ 각 n번째 λ§ˆμ„λ‘œ κ°€λŠ” μ΅œλ‹¨ 경둜λ₯Ό κ΅¬ν•˜κ³  배열에 μ €μž₯ν•œλ‹€. (fromParty)
  • λ§ˆμ§€λ§‰μœΌλ‘œ 각 λ§ˆμ„μ˜ μœ„μΉ˜λ³„λ‘œ 두 λ°°μ—΄μ˜ 값을 λ”ν•œ κ°’ 쀑 κ°€μž₯ 큰 값을 좜λ ₯ν•˜λ©΄ λœλ‹€.
  • λ¨Όμ €, x번째 λ§ˆμ„μ—μ„œ n번째 λ§ˆμ„λ‘œ κ°€λŠ” μ΅œλ‹¨ κ²½λ‘œκ°€ μ €μž₯된 fromPartyλ₯Ό κ΅¬ν•˜λŠ” 방식은 μ „ν˜•μ μΈ λ‹€μ΅μŠ€νŠΈλΌ μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•œλ‹€.
  • λ‹€μ΅μŠ€νŠΈλΌ μ•Œκ³ λ¦¬μ¦˜μ„ μ„€λͺ…ν•˜μžλ©΄ λ‹€μŒκ³Ό κ°™λ‹€.
    • 좜발 λ…Έλ“œμ—μ„œ 각 λ…Έλ“œλ³„λ‘œ 갈 수 μžˆλŠ” μ΅œλ‹¨ 경둜λ₯Ό μ €μž₯ν•  배열을 1e9 κ°’μœΌλ‘œ μ΄ˆκΈ°ν™”ν•΄μ„œ μ„ μ–Έν•œλ‹€.
    • 이 배열에 좜발 λ…Έλ“œμ— ν•΄λ‹Ήν•˜λŠ” 값은 0으둜 μ΄ˆκΈ°ν™”ν•˜κ³ , (0, 좜발 λ…Έλ“œ)λ₯Ό heap에 λ„£μ–΄μ€€λ‹€.
    • 이제 heap을 popν•˜λ©΄μ„œ popν•œ λ…Έλ“œμ— μ—°κ²°λœ λ…Έλ“œμ™€ κ°€μ€‘μΉ˜λ“€μ„ νƒμƒ‰ν•œλ‹€. (heap을 μ‚¬μš©ν–ˆκΈ° λ•Œλ¬Έμ— μ €μž₯된 κ°’ 쀑 κ°€μ€‘μΉ˜κ°€ κ°€μž₯ μž‘μ€ 값이 μš°μ„ μ μœΌλ‘œ popλœλ‹€.)
    • 탐색 κ³Όμ •μ—μ„œ ν˜„μž¬ μ΅œλ‹¨ 경둜둜 μ €μž₯된 값보닀 popν•œ κ°€μ€‘μΉ˜ + ν˜„μž¬ λ…Έλ“œμ™€ μ—°κ²°λœ λ…Έλ“œμ™€μ˜ κ°€μ€‘μΉ˜ 값이 더 μž‘λ‹€λ©΄ ν˜„μž¬ μ΅œλ‹¨ 경둜λ₯Ό μ—…λ°μ΄νŠΈν•œλ‹€.
    • 이 과정을 heap에 μ‘΄μž¬ν•˜λŠ” 값이 없을 λ•ŒκΉŒμ§€ λ°˜λ³΅ν•˜λ©΄ 좜발 λ…Έλ“œμ—μ„œ 각 λ…Έλ“œλ‘œ ν–₯ν•˜λŠ” μ΅œλ‹¨ 경둜λ₯Ό ꡬ할 수 μžˆλ‹€. 
  • μ—¬κΈ°μ„œ x번째 λ§ˆμ„μ—μ„œ 각 n번째 λ§ˆμ„λ‘œ κ°€λŠ” μ΅œλ‹¨ 경둜인 fromPartyλ₯Ό ꡬ할 λ•ŒλŠ” μž…λ ₯받은 기쑴의 경둜λ₯Ό μ‚¬μš©ν•˜λ©΄ λœλ‹€.
    • 예제λ₯Ό 예둜 λ“€λ©΄, 2->1, 2->3, 2->4둜 κ°€λŠ” μ΅œλ‹¨ 경둜λ₯Ό κ΅¬ν•˜λŠ” 것이닀.
  • ν•˜μ§€λ§Œ, 각 n번째 λ§ˆμ„μ—μ„œ x번째 λ§ˆμ„λ‘œ κ°€λŠ” μ΅œλ‹¨ 경둜인 toPartyλŠ” μž…λ ₯받은 기쑴의 경둜λ₯Ό μ—­λ°©ν–₯으둜 μ €μž₯ν•΄μ„œ ꡬ해야 ν•œλ‹€.
    • 예제λ₯Ό 예둜 λ“€λ©΄, 1->2, 3->2, 4->2둜 κ°€λŠ” μ΅œλ‹¨ 경둜λ₯Ό ꡬ해야 ν•˜λŠ”λ°, 이것은 각 λ…Έλ“œλ§ˆλ‹€ λ‹€μ΅μŠ€νŠΈλΌλ₯Ό μ‹€ν–‰ν•΄μ•Ό ν•˜λ―€λ‘œ μ‹œκ°„λ³΅μž‘λ„κ°€ 컀질 수 밖에 μ—†λ‹€. 
    • κ·Έλž˜μ„œ 기쑴의 경둜λ₯Ό μ—­λ°©ν–₯으둜 μ €μž₯ν•΄μ„œ λ‹€μ΅μŠ€νŠΈλΌλ₯Ό ν•œ 번만 μ‹€ν–‰ν•΄μ„œ 2->1, 2->3, 2->4λ₯Ό κ΅¬ν•œλ‹€.
      • 기쑴의 경둜둜 ν•œ 1->2, 3->2, 4->2 κ°’κ³Ό λ™μΌν•œ 값을 κ°€μ§€κ²Œ λœλ‹€.