We will find a way, we always have.

-interstellar

Problem Solving/λ°±μ€€

[λ°±μ€€] 1865번: μ›œν™€ - 파이썬

Redddy 2022. 8. 6. 10:05

πŸ”ˆ 문제

λ•ŒλŠ” 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λ₯Ό 좜λ ₯ν•œλ‹€.

 

πŸ“š λ¬Έμ œ ν’€μ΄

이 문제λ₯Ό 보고 μ²˜μŒμ—λŠ” μ›œν™€μ€ μ œμ™Έν•˜κ³  데이크슀트라 μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•΄μ„œ 각각의 μ΅œλ‹¨κ±°λ¦¬λ₯Ό μ•Œμ•„λ‚Έ λ‹€μŒ μ›œν™€μ˜ λ§ˆμ΄λ„ˆμŠ€ 값을 μ—°μ‚°ν•˜μ—¬ μŒμˆ˜κ°€ λ‚˜μ˜€λŠ” 거리가 μžˆλ‹€λ©΄ 'YES'λ₯Ό 좜λ ₯ν•˜λ©΄ λ˜κ² λ‹€κ³  μƒκ°ν–ˆλ‹€.

κ·Έλ ‡κ²Œ iλ…Έλ“œμ—μ„œ μΆœλ°œν–ˆμ„λ•Œ λ‹€λ₯Έ λ…Έλ“œμ˜ μ΅œλ‹¨κ±°λ¦¬λ₯Ό μ•Œμ•„λƒˆλŠ”λ° λ‹€μ‹œ λŒμ•„μ˜€λŠ” 거리λ₯Ό κ³„μ‚°ν•˜λ €λ©΄ 또 λ‹€λ₯Έ κ΅¬ν˜„μ„ ν•΄μ•Όν–ˆλ‹€...γ…‹γ…‹γ…Ž

λ…Έλ“œκ°€ 총 3개 μžˆμ„ λ•Œ 1번 λ…Έλ“œμ—μ„œ μΆœλ°œν•˜λ©΄ 결과값은 예λ₯Ό λ“€μ–΄ [0, 3, 1] μ΄λŸ°μ‹μœΌλ‘œ 좜발 λ…Έλ“œλŠ” 0으둜 결과값이 λ‚˜μ˜€κΈ° λ•Œλ¬Έμ— ν•œλ°”ν€΄ λŒμ•„μ™”μ„ λ•Œ 거리λ₯Ό μ•Œμˆ˜κ°€ μ—†μ—ˆλ‹€.

 

밑에 μ•Œκ³ λ¦¬μ¦˜ λΆ„λ₯˜λ₯Ό λ³΄μ•˜λŠ”λ° 벨만 ν¬λ“œ μ•Œκ³ λ¦¬μ¦˜μ΄λΌκ³  μ ν˜€μžˆμ—ˆλ‹€. κ·Έλž˜μ„œ μ²˜μŒμ—λŠ” 벨만 ν¬λ“œ μ•Œκ³ λ¦¬μ¦˜μ€ λ°”λ‘œ ν•œλ°”ν€΄ λŒμ•„μ˜€λŠ” 값을 ꡬ할 수 μžˆμ„κΉŒν•˜κ³  ꡬ글링해본 κ²°κ³Ό 그건 μ•„λ‹ˆμ—ˆλ‹€..γ…Ž

 

데이크슀트라 μ•Œκ³ λ¦¬μ¦˜κ³Ό 벨만 ν¬λ“œμ˜ 차이점은 λ°”λ‘œ 음수의 간선에 μžˆμ—ˆλ‹€.

데이크슀트라 μ•Œκ³ λ¦¬μ¦˜μ€ 음수의 간선을 인지 λͺ»ν•˜κ³  κ·Έλƒ₯ μ§€λ‚˜μ³ 버린닀. κ·Έλ¦¬λ””ν•˜κ²Œ μž‘λ™ν•˜κΈ° λ•Œλ¬Έμ— 뒀에 μžˆλŠ” 음수의 간선은 νŒŒμ•…ν•˜μ§€ λͺ»ν•˜κ³  μ§€λ‚˜μ³ λ²„λ¦°λ‹€λŠ” 것이닀. 이에 반면 벨만 ν¬λ“œ μ•Œκ³ λ¦¬μ¦˜μ€ μ΄μ›ƒν•œ λ…Έλ“œλ₯Ό μ „λΆ€ λ°©λ¬Έν•˜κΈ° λ•Œλ¬Έμ— 음수의 κ°„μ„ μ˜ 쑴재λ₯Ό μ•Œ 수 μžˆλ‹€.

 

λ„λ‘œμ™€ μ›œν™€μ„ λ”•μ…”λ„ˆλ¦¬μ— ν•œλ²ˆμ— λ‹΄λŠ”λ‹€. λ…Έλ“œλ₯Ό μž‡λŠ” λ„λ‘œλ‚˜ μ›œν™€μ€ ν•˜λ‚˜ 이상이 μ‘΄μž¬ν•  μˆ˜λ„ 있기 λ•Œλ¬Έμ— κ°€μž₯ μž‘μ€ κ°’λ§Œ μ‘΄μž¬ν•˜λ„λ‘ μ²˜λ¦¬ν–ˆλ‹€.

μš”κ±° 잘 μ²˜λ¦¬ν•˜κ³  벨만 ν¬λ“œ μ•Œκ³ λ¦¬μ¦˜ λŒλ¦¬λ‹ˆ μ •λ‹΅ νŒμ •μ„ λ°›μ•˜λ‹€.

 

πŸ’» μ½”λ“œ

import sys
input = sys.stdin.readline

# 벨만 ν¬λ“œ μ•Œκ³ λ¦¬μ¦˜ κ΅¬ν˜„
def bellman_ford(graph, start):
    distance= dict()
    for node in graph:
        distance[node] = 5000 * 10000 # λ¬΄ν•œ κ°’μœΌλ‘œ μ΄ˆκΈ°ν™”
    distance[start] = 0

    for i in range(len(graph)-1):
        for node in graph:
            for neighbor in graph[node]:
                if distance[neighbor] > distance[node] + graph[node][neighbor]:
                    distance[neighbor] = distance[node] + graph[node][neighbor]
    
    for node in graph:
        for neighbor in graph[node]:
        	# ν•œλ²ˆ 더 λŒμ•˜μ„ λ•Œλ„ 이게 κ°€λŠ₯ν•˜λ‹€λ©΄ μ‹œκ°„ μ€„μŒ
            if distance[neighbor] > distance[node] + graph[node][neighbor]:
                return 'YES'
    
    return 'NO'


for _ in range(int(input())):
    n,m,w = map(int,input().split())
    graph = dict()
    # ν‹€λ§Œλ“€κΈ°
    for i in range(1, n+1):
        graph[i] = {}

    for j in range(m):
        s,e,t=map(int,input().split())
        # 이전에 이미 λ„λ‘œκ°€ μžˆλ‹€λ©΄
        if e in graph[s]:
        # μ΅œμ†Œκ°’μœΌλ‘œ μ—…λ°μ΄νŠΈ
            graph[s][e] = min(graph[s][e], t)
        else:
            graph[s][e] = t

        if s in graph[e]:
            graph[e][s] = min(graph[e][s], t)
        else:
            graph[e][s] = t

    for k in range(w):
    # μ›œν™€
        s,e,t = map(int,input().split())
        graph[s][e] = -t

    print(bellman_ford(graph, 1))

 

🍭 μ‹œν–‰μ°©μ˜€

ν‹€λ¦° μ΄μœ λŠ” λ¬΄ν•œ 값을 λ„ˆλ¬΄ μž‘κ²Œ μž‘μ•˜κΈ° λ•Œλ¬Έμ΄λ‹€. μ‹œκ°„ μ΄ˆκ³Όκ°€ λ‚œ μ΄μœ λŠ” λͺ¨λ“  λ…Έλ“œμ—μ„œ 값을 μ²΄ν¬ν–ˆκΈ° λ•Œλ¬Έμ΄λ‹€. ν•΄λ‹Ή 문제(Not Problem)λŠ” 좜발 λ…Έλ“œλ₯Ό λ”°λ‘œ 지정해주지 μ•Šμ•˜λŠ”λ° μ†ŒμŠ€μ½”λ“œμ—λŠ” 1번 λ…Έλ“œλ§Œ νƒμƒ‰μ„ν•˜κ³  λ°”λ‘œ 닡을 μœ μΆ”ν•˜μ˜€λ‹€. μ™œλƒ μ „λΆ€ μ—°κ²°λ˜μ–΄ μžˆλŠ” κ·Έλž˜ν”„μ΄κΈ° λ•Œλ¬ΈμΈκ±° κ°™κΈ΄ν•œλ° μ •ν™•ν•˜κ²Œ 증λͺ…ν•˜μ§€λŠ” λͺ»ν•˜κ² λ‹€. 아직 벨만 ν¬λ“œ μ•Œκ³ λ¦¬μ¦˜μ„ μ™„λ²½ν•˜κ²Œ μ΄ν•΄ν•˜μ§€λŠ” λͺ»ν•˜κ² μœΌλ‚˜ μž‘λ™μ›λ¦¬λŠ” 감이 온거 κ°™λ‹€.

πŸ”— 문제링크 μ›œν™€

 

1865번: μ›œν™€

첫 번째 μ€„μ—λŠ” ν…ŒμŠ€νŠΈμΌ€μ΄μŠ€μ˜ 개수 TC(1 ≤ TC ≤ 5)κ°€ 주어진닀. 그리고 두 번째 쀄뢀터 TC개의 ν…ŒμŠ€νŠΈμΌ€μ΄μŠ€κ°€ μ°¨λ‘€λ‘œ μ£Όμ–΄μ§€λŠ”λ° 각 ν…ŒμŠ€νŠΈμΌ€μ΄μŠ€μ˜ 첫 번째 μ€„μ—λŠ” μ§€μ μ˜ 수 N(1 ≤ N ≤ 500),

www.acmicpc.net