Skip to content

Latest commit

Β 

History

History
92 lines (79 loc) Β· 4.1 KB

File metadata and controls

92 lines (79 loc) Β· 4.1 KB

음수 간선이 ν¬ν•¨λœ μƒν™©μ—μ„œμ˜ μ΅œλ‹¨ 거리 문제

  • λ°±μ€€ 'νƒ€μž„λ¨Έμ‹ ' 문제 : https://www.acmicpc.net/problem/11657
  • N개의 λ„μ‹œκ°€ μžˆλ‹€. 그리고 ν•œ λ„μ‹œμ—μ„œ μΆœλ°œν•˜μ—¬ λ‹€λ₯Έ λ„μ‹œμ— λ„μ°©ν•˜λŠ” λ²„μŠ€κ°€ M개 μžˆλ‹€. 각 λ²„μŠ€λŠ” A,B,C둜 λ‚˜νƒ€λ‚Ό 수 μžˆλŠ”λ° AλŠ” μ‹œμž‘λ„μ‹œ, BλŠ” λ„μ°©λ„μ‹œ, CλŠ” λ²„μŠ€λ₯Ό 타고 μ΄λ™ν•˜λŠ”λ° κ±Έλ¦¬λŠ” μ‹œκ°„μ΄λ‹€. μ‹œκ°„ Cκ°€ μ–‘μˆ˜κ°€ μ•„λ‹Œ κ²½μš°κ°€ μžˆλ‹€. C = 0인 κ²½μš°μ—λŠ” μˆœκ°„ 이동을 ν•˜λŠ” 경우, C < 0인 κ²½μš°λŠ” νƒ€μž„λ¨Έμ‹ μœΌλ‘œ μ‹œκ°„μ„ λ˜λŒμ•„κ°€λŠ” κ²½μš°μ΄λ‹€. 1번 λ„μ‹œμ—μ„œ μΆœλ°œν•΄μ„œ λ‚˜λ¨Έμ§€ λ„μ‹œλ‘œ κ°€λŠ” κ°€μž₯ λΉ λ₯Έ μ‹œκ°„μ„ κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜λΌ
  • λ„μ‹œμ˜ 개수 : N(1 <= N <= 500)
  • λ²„μŠ€ λ…Έμ„ μ˜ 개수 : M(1<= M <= 6000)

벨만 ν¬λ“œ μ΅œλ‹¨ 경둜 μ•Œκ³ λ¦¬μ¦˜

  • 음수 간선에 κ΄€ν•˜μ—¬ μ΅œλ‹¨ 경둜 λ¬Έμ œλŠ” λ‹€μŒκ³Ό 같이 λΆ„λ₯˜ν•  수 μžˆλ‹€

    1. λͺ¨λ“  간선이 μ–‘μˆ˜μΈ 경우
    2. 음수 간선이 μžˆλŠ” 경우
      1. 음수 κ°„μ„  μˆœν™˜μ€ μ—†λŠ” 경우
      2. 음수 κ°„μ„  μˆœν™˜μ΄ μžˆλŠ” 경우
  • 벨만 ν¬λ“œ μ΅œλ‹¨ 경둜 μ•Œκ³ λ¦¬μ¦˜μ€ 음의 간선이 ν¬ν•¨λœ μƒν™©μ—μ„œλ„ μ‚¬μš©ν•  수 μžˆλ‹€

    • λ˜ν•œ 음수 κ°„μ„ μ˜ μˆœν™˜μ„ 감지할 수 μžˆλ‹€
    • 벨만 ν¬λ“œμ˜ κΈ°λ³Έ μ‹œκ°„ λ³΅μž‘λ„λŠ” O(VE)둜 λ‹€μ΅μŠ€νŠΈλΌ μ•Œκ³ λ¦¬μ¦˜μ— λΉ„ν•΄ λŠλ¦¬λ‹€
  • 벨만 ν¬λ“œ μ•Œκ³ λ¦¬μ¦˜μ€ λ‹€μŒκ³Ό κ°™λ‹€

    1. 좜발 λ…Έλ“œλ₯Ό μ„€μ •ν•œλ‹€
    2. μ΅œλ‹¨ 거리 ν…Œμ΄λΈ”μ„ μ΄ˆκΈ°ν™”ν•œλ‹€
    3. λ‹€μŒμ˜ 과정을 N - 1번 λ°˜λ³΅ν•œλ‹€
      1. 전체 κ°„μ„  E개λ₯Ό ν•˜λ‚˜μ”© ν™•μΈν•œλ‹€
      2. 각 간선을 거쳐 λ‹€λ₯Έ λ…Έλ“œλ‘œ κ°€λŠ” λΉ„μš©μ„ κ³„μ‚°ν•˜μ—¬ μ΅œλ‹¨ 거리 ν…Œμ΄λΈ”μ„ κ°±μ‹ ν•œλ‹€
  • λ§Œμ•½ 음수 κ°„μ„  μˆœν™˜μ΄ λ°œμƒν•˜λŠ”μ§€ μ²΄ν¬ν•˜κ³  μ‹Άλ‹€λ©΄ 3번의 과정을 ν•œ 번 더 μˆ˜ν–‰ν•œλ‹€

    • μ΄λ•Œ μ΅œλ‹¨ 거리 ν…Œμ΄λΈ”μ΄ κ°±μ‹ λœλ‹€λ©΄ 음수 κ°„μ„  μˆœν™˜μ΄ μ‘΄μž¬ν•˜λŠ” 것이닀

λ‹€μ΅μŠ€νŠΈλΌ VS 벨만 ν¬λ“œ

  • λ‹€μ΅μŠ€νŠΈλΌ μ•Œκ³ λ¦¬μ¦˜
    • 맀번 λ°©λ¬Έν•˜μ§€ μ•Šμ€ λ…Έλ“œ μ€‘μ—μ„œ μ΅œλ‹¨ 거리가 κ°€μž₯ 짧은 λ…Έλ“œλ₯Ό μ„ νƒν•œλ‹€
    • 음수 간선이 μ—†λ‹€λ©΄ 졜적의 ν•΄λ₯Ό 찾을 수 μžˆλ‹€
  • 벨만 ν¬λ“œ μ•Œκ³ λ¦¬μ¦˜
    • 맀번 λͺ¨λ“  간선을 μ „λΆ€ ν™•μΈν•œλ‹€
      • λ”°λΌμ„œ λ‹€μ΅μŠ€νŠΈλΌ μ•Œκ³ λ¦¬μ¦˜μ—μ„œμ˜ 졜적의 ν•΄λ₯Ό 항상 ν¬ν•¨ν•œλ‹€
    • λ‹€μ΅μŠ€νŠΈλΌ μ•Œκ³ λ¦¬μ¦˜μ— λΉ„ν•΄μ„œ μ‹œκ°„μ΄ 였래 κ±Έλ¦¬μ§€λ§Œ 음수 κ°„μ„  μˆœν™˜μ„ 탐지할 수 μžˆλ‹€
import sys
input = sys.stdin.readline
INF = int(1e9) # λ¬΄ν•œμ„ μ˜λ―Έν•˜λŠ” κ°’μœΌλ‘œ 10얡을 μ„€μ •

def bf(start):
    # μ‹œμž‘ λ…Έλ“œμ— λŒ€ν•΄μ„œ μ΄ˆκΈ°ν™”
    dist[start] = 0
    # 전체 n번의 λΌμš΄λ“œ(round)λ₯Ό 반볡
    for i in range(n):
        # λ§€ λ°˜λ³΅λ§ˆλ‹€ "λͺ¨λ“  κ°„μ„ "을 ν™•μΈν•˜λ©°
        for j in range(m):
            cur = edges[j][0]
            next_node = edges[j][1]
            cost = edges[j][2]
            # ν˜„μž¬ 간선을 κ±°μ³μ„œ λ‹€λ₯Έ λ…Έλ“œλ‘œ μ΄λ™ν•˜λŠ” 거리가 더 짧은 경우
            if dist[cur] != INF and dist[next_node] > dist[cur] + cost:
                dist[next_node] = dist[cur] + cost
                # n번째 λΌμš΄λ“œμ—μ„œλ„ 값이 κ°±μ‹ λœλ‹€λ©΄ 음수 μˆœν™˜μ΄ 쑴재
                if i == n - 1:
                    return True
    return False

# λ…Έλ“œμ˜ 개수, κ°„μ„ μ˜ 개수 μž…λ ₯λ°›κΈ°
n, m = map(int, input().split())
# λͺ¨λ“  간선에 λŒ€ν•œ 정보λ₯Ό λ‹΄λŠ” 리슀트 λ§Œλ“€κΈ°
edges = []
# μ΅œλ‹¨ 거리 ν…Œμ΄λΈ”μ„ λͺ¨λ‘ λ¬΄ν•œμœΌλ‘œ μ΄ˆκΈ°ν™”
dist = [INF] * (n+1)

# λͺ¨λ“  κ°„μ„  정보λ₯Ό μž…λ ₯λ°›κΈ°
for _ in range(m):
    a,b,c = map(int, input().split())
    # a번 λ…Έλ“œμ—μ„œ b번 λ…Έλ“œλ‘œ κ°€λŠ” λΉ„μš©μ΄ cλΌλŠ” 의미
    edges.append((a,b,c))

# 벨만 ν¬λ“œ μ•Œκ³ λ¦¬μ¦˜μ„ μˆ˜ν–‰
negative_cycle = bf(1) # 1번 λ…Έλ“œκ°€ μ‹œμž‘ λ…Έλ“œ

if negative_cycle:
    print("-1")
else:
    # 1번 λ…Έλ“œλ₯Ό μ œμ™Έν•œ λ‹€λ₯Έ λͺ¨λ“  λ…Έλ“œλ‘œ κ°€κΈ° μœ„ν•œ μ΅œλ‹¨ 거리 좜λ ₯
    for i in range(2, n+1):
        # 도달할 수 μ—†λŠ” 경우, -1을 좜λ ₯
        if dist[i] == INF:
            print("-1")
        # 도달할 수 μžˆλŠ” 경우 거리λ₯Ό 좜λ ₯
        else:
            print(dist[i])