[Baekjoon/πŸ₯‡β…’] 1865: μ›œν™€β­οΈ

3 λΆ„ μ†Œμš”

πŸ™‹β€β™€οΈ μ›œν™€

λ•ŒλŠ” 2020λ…„, λ°±μ€€μ΄λŠ” μ›”λ“œλ‚˜λΌμ˜ ν•œ ꡭ민이닀. μ›”λ“œλ‚˜λΌμ—λŠ” N개의 지점이 있고 N개의 지점 μ‚¬μ΄μ—λŠ” M개의 λ„λ‘œμ™€ W개의 μ›œν™€μ΄ μžˆλ‹€. (단 λ„λ‘œλŠ” λ°©ν–₯이 μ—†μœΌλ©° μ›œν™€μ€ λ°©ν–₯이 μžˆλ‹€.) μ›œν™€μ€ μ‹œμž‘ μœ„μΉ˜μ—μ„œ 도착 μœ„μΉ˜λ‘œ κ°€λŠ” ν•˜λ‚˜μ˜ 경둜인데, νŠΉμ΄ν•˜κ²Œλ„ 도착을 ν•˜κ²Œ 되면 μ‹œμž‘μ„ ν•˜μ˜€μ„ λ•Œλ³΄λ‹€ μ‹œκ°„μ΄ λ’€λ‘œ κ°€κ²Œ λœλ‹€. μ›œν™€ λ‚΄μ—μ„œλŠ” μ‹œκ³„κ°€ 거꾸둜 κ°„λ‹€κ³  μƒκ°ν•˜μ—¬λ„ μ’‹λ‹€.

μ‹œκ°„ 여행을 맀우 μ’‹μ•„ν•˜λŠ” λ°±μ€€μ΄λŠ” ν•œ 가지 κΆκΈˆμ¦μ— λΉ μ‘Œλ‹€. ν•œ μ§€μ μ—μ„œ μΆœλ°œμ„ ν•˜μ—¬μ„œ μ‹œκ°„μ—¬ν–‰μ„ ν•˜κΈ° μ‹œμž‘ν•˜μ—¬ λ‹€μ‹œ μΆœλ°œμ„ ν•˜μ˜€λ˜ μœ„μΉ˜λ‘œ λŒμ•„μ™”μ„ λ•Œ, μΆœλ°œμ„ ν•˜μ˜€μ„ λ•Œλ³΄λ‹€ μ‹œκ°„μ΄ λ˜λŒμ•„κ°€ μžˆλŠ” κ²½μš°κ°€ μžˆλŠ”μ§€ μ—†λŠ”μ§€ κΆκΈˆν•΄μ‘Œλ‹€. μ—¬λŸ¬λΆ„μ€ 백쀀이λ₯Ό 도와 이런 일이 κ°€λŠ₯ν•œμ§€ λΆˆκ°€λŠ₯ν•œμ§€ κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ—¬λΌ.

πŸ™‹β€β™€οΈ μž…λ ₯

첫 번째 μ€„μ—λŠ” ν…ŒμŠ€νŠΈμΌ€μ΄μŠ€μ˜ 개수 TC(1 ≀ TC ≀ 5)κ°€ 주어진닀. 그리고 두 번째 쀄뢀터 TC개의 ν…ŒμŠ€νŠΈμΌ€μ΄μŠ€κ°€ μ°¨λ‘€λ‘œ μ£Όμ–΄μ§€λŠ”λ° 각 ν…ŒμŠ€νŠΈμΌ€μ΄μŠ€μ˜ 첫 번째 μ€„μ—λŠ” μ§€μ μ˜ 수 N(1 ≀ N ≀ 500), λ„λ‘œμ˜ 개수 M(1 ≀ M ≀ 2500), μ›œν™€μ˜ 개수 W(1 ≀ W ≀ 200)이 주어진닀. 그리고 두 번째 쀄뢀터 M+1번째 쀄에 λ„λ‘œμ˜ 정보가 μ£Όμ–΄μ§€λŠ”λ° 각 λ„λ‘œμ˜ μ •λ³΄λŠ” S, E, T μ„Έ μ •μˆ˜λ‘œ 주어진닀. S와 EλŠ” μ—°κ²°λœ μ§€μ μ˜ 번호, TλŠ” 이 λ„λ‘œλ₯Ό 톡해 μ΄λ™ν•˜λŠ”λ° κ±Έλ¦¬λŠ” μ‹œκ°„μ„ μ˜λ―Έν•œλ‹€. 그리고 M+2번째 쀄뢀터 M+W+1번째 μ€„κΉŒμ§€ μ›œν™€μ˜ 정보가 S, E, T μ„Έ μ •μˆ˜λ‘œ μ£Όμ–΄μ§€λŠ”λ° SλŠ” μ‹œμž‘ 지점, EλŠ” 도착 지점, TλŠ” μ€„μ–΄λ“œλŠ” μ‹œκ°„μ„ μ˜λ―Έν•œλ‹€. TλŠ” 10,000보닀 μž‘κ±°λ‚˜ 같은 μžμ—°μˆ˜ λ˜λŠ” 0이닀.

두 지점을 μ—°κ²°ν•˜λŠ” λ„λ‘œκ°€ ν•œ κ°œλ³΄λ‹€ λ§Žμ„ μˆ˜λ„ μžˆλ‹€. μ§€μ μ˜ λ²ˆν˜ΈλŠ” 1λΆ€ν„° NκΉŒμ§€ μžμ—°μˆ˜λ‘œ 쀑볡 없이 맀겨져 μžˆλ‹€.

πŸ™‹β€β™€οΈ 좜λ ₯

TC개의 쀄에 κ±Έμ³μ„œ λ§Œμ•½μ— μ‹œκ°„μ΄ μ€„μ–΄λ“€λ©΄μ„œ 좜발 μœ„μΉ˜λ‘œ λŒμ•„μ˜€λŠ” 것이 κ°€λŠ₯ν•˜λ©΄ YES, λΆˆκ°€λŠ₯ν•˜λ©΄ NOλ₯Ό 좜λ ₯ν•œλ‹€.


πŸ‘©β€πŸ’» μ–΄λ–€ μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•΄μ•Ό ν• κΉŒ?

μš°μ„  ν•˜λ‚˜μ˜ μ •μ μ—μ„œ λ‹€λ₯Έ λͺ¨λ“  μ •μ κΉŒμ§€μ˜ μ΅œλ‹¨κ±°λ¦¬λ₯Ό κ΅¬ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ€ μ—¬λŸ¬ κ°œκ°€ μ‘΄μž¬ν•œλ‹€.

κ·Έλ ‡λ‹€λ©΄ 각각의 μ•Œκ³ λ¦¬μ¦˜μ„ μ™œ μ‚¬μš©ν•˜λ©΄ μ•ˆλ˜λŠ”μ§€λ₯Ό νŒŒμ•…ν•΄λ³΄μž!!

  1. λ‹€μ΅μŠ€νŠΈλΌ μ•Œκ³ λ¦¬μ¦˜
    • ν•΄λ‹Ή λ¬Έμ œμ—μ„œλŠ” 음의 간선이 μ‘΄μž¬ν•˜λ―€λ‘œ λ‹€μ΅μŠ€νŠΈλΌλŠ” μ‚¬μš©ν•  수 μ—†λ‹€.
  2. ν”Œλ‘œμ΄λ“œ μ›Œμ…œ
    • ν”Œλ‘œμ΄λ“œ μ›Œμ…œμ„ ν†΅ν•΄μ„œλ„ 음의 κ°€μ€‘μΉ˜λ₯Ό λ‹€λ£° 수 μžˆλ‹€.
    • 문제 속 μ •μ μ˜ κ°œμˆ˜κ°€ 500λΌλŠ” μ μ—μ„œ μ‹œκ°„ λ³΅μž‘λ„κ°€ O(N^3)인 ν”Œλ‘œμ΄λ“œ μ›Œμ…œμ„ μ‚¬μš©ν•  수 μžˆλ‹€.
    • ν•˜μ§€λ§Œ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€κ°€ μ΅œλŒ€ 5κ°œλΌλŠ” μ μ—μ„œ μ‹œκ°„μ΄ˆκ³Όκ°€ λ°œμƒν•œλ‹€.
  3. λ²¨λ§Œν¬λ“œ μ•Œκ³ λ¦¬μ¦˜
    • 음의 κ°€μ€‘μΉ˜λ₯Ό λ‹€λ£° 수 μžˆλ‹€.
    • O(VE)둜 ν”Œλ‘œμ΄λ“œ μ›Œμ…œλ³΄λ‹€ μ‹œκ°„ λ³΅μž‘λ„κ°€ μž‘λ‹€.

λ”°λΌμ„œ ν•΄λ‹Ή λ¬Έμ œλŠ” λ²¨λ§Œν¬λ“œ μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ ν•΄κ²°ν•΄μ•Ό ν•œλ‹€!!

(ν•„μžλŠ” 이번 문제λ₯Ό 톡해 처음으둜 λ²¨λ§Œν¬λ“œ μ•Œκ³ λ¦¬μ¦˜μ„ 처음 μ ‘ν–ˆλ‹€..γ…Žγ…Žγ…Žγ…Ž ν•˜μ§€λ§Œ ν•™μŠ΅μ„ ν•˜κ³  λ‚˜λ‹ˆ μ•Œκ³ λ¦¬μ¦˜μ΄ 생각보닀 κ°„λ‹¨ν•˜κ³ , 음의 κ°€μ€‘μΉ˜λ₯Ό λ‹€λ£° λ•Œ μœ μš©ν•˜κ²Œ μ‚¬μš©ν•  수 μžˆμ„ 것 κ°™λ‹€!!)


πŸ‘©β€πŸ’» Code: μ‹œμž‘ 정점을 λ‘” λ²¨λ§Œν¬λ“œ

# bellman ford: μ‹œκ°„μ΄ˆκ³Ό
import sys
input = sys.stdin.readline
INF = int(1e9)

tc = int(input())

def bellmanFord(start):
    dist = [INF] * (n+1)
    dist[start] = 0

    for i in range(n):
        for s, e, t in edges:
            
            if dist[s] != INF and dist[e] > dist[s] + t:
                dist[e] = dist[s]+t

                if i == n-1:
                    return True

    return False

for _ in range(tc):
    n, m, w = map(int, input().split())
    edges = []

    for _ in range(m):
        s, e, t = map(int, input().split())
        edges.append((s, e, t))
        edges.append((e, s, t))

    for _ in range(w):
        s, e, t = map(int, input().split())
        edges.append((s, e, -t))


    check = 0
    for i in range(1, n+1):
        if bellmanFord(i):
            check = 1
            break
    if check:
        print("YES")
    else:
        print("NO")

ν•΄λ‹Ή λ¬Έμ œλŠ” μ‹œμž‘ 정점이 μ£Όμ–΄μ Έ μžˆμ§€ μ•Šλ‹€. λ”°λΌμ„œ λͺ¨λ“  정점을 λ‹€ ν™•μΈν•˜λŠ” λ°©μ‹μœΌλ‘œ μ ‘κ·Όν•œλ‹€λ©΄(μœ„ μ½”λ“œ) μ‹œκ°„μ΄ˆκ³Όκ°€ λ°œμƒν•œλ‹€.

κ·Έλ ‡λ‹€λ©΄ μ–΄λ–»κ²Œ μ ‘κ·Όν•΄μ•Ό ν• κΉŒ?? μ‹œμž‘μ •μ μ„ 신경쓰지 μ•Šκ³  λ‹¨μˆœνžˆ 음의 μ‚¬μ΄ν΄λ§Œμ„ 확인할 순 μ—†μ„κΉŒ??

κ°€λŠ₯이닀!!!


πŸ‘©β€πŸ’» Code: 음의 μ‚¬μ΄ν΄λ§Œμ„ ν™•μΈν•˜λŠ” λ²¨λ§Œν¬λ“œ

# bellman ford: λ¦¬νŒ©ν† λ§ (μ •λ‹΅)
import sys
input = sys.stdin.readline
INF = int(1e9)

tc = int(input())

def bellmanFord():
    dist = [INF] * (n+1)

    for i in range(n):
        for s, e, t in edges:
            
            # μ‹œμž‘μ •μ κ³Ό μΈμ ‘ν•œμ§€λ₯Ό ν™•μΈν•˜λŠ” μ½”λ“œκ°€ λΉ μ§€κ²Œ λœλ‹€.
            if dist[e] > dist[s] + t:
                dist[e] = dist[s]+t

                if i == n-1:
                    return True

    return False

for _ in range(tc):
    n, m, w = map(int, input().split())
    edges = []

    for _ in range(m):
        s, e, t = map(int, input().split())
        edges.append((s, e, t))
        edges.append((e, s, t))

    for _ in range(w):
        s, e, t = map(int, input().split())
        edges.append((s, e, -t))

    # μ‹œμž‘ 정점이 μ—†μ–΄ ν•œ 번의 μ‹€ν–‰μœΌλ‘œ 음의 μ‚¬μ΄ν΄λ§Œμ„ νŒŒμ•…ν•œλ‹€.
    if bellmanFord():
        print("YES")
    else:
        print("NO")

πŸ“ μ°Έκ³  자료

λŒ“κΈ€λ‚¨κΈ°κΈ°