개발/algorithm

[백준 1865번] 웜홀 - python

zzi_on2 2022. 3. 17. 21:03

문제 링크

https://www.acmicpc.net/problem/1865

 

1865번: 웜홀

첫 번째 줄에는 테스트케이스의 개수 TC(1 ≤ TC ≤ 5)가 주어진다. 그리고 두 번째 줄부터 TC개의 테스트케이스가 차례로 주어지는데 각 테스트케이스의 첫 번째 줄에는 지점의 수 N(1 ≤ N ≤ 500),

www.acmicpc.net

풀이

 - 벨만 포드 문제 

문제의 뜻을 웜홀을 거쳤을 때 최단 거리가 줄어들 수 있는지 물어보는 줄 알았는데,

음수 사이클이 존재하는지 물어보는 문제였다. 

이 때, 어느 지점에서 출발하는지에 관계없이 음수 사이클이 존재하는지만 판단하면 되므로

dist[node] != INF 조건을 삭제해주어야 한다. 

dist[node] != INF 는 dist[start] = 0으로 설정한 시작 지점에서부터 이어진 노드의 최소 거리를 구하기 위한 조건이기 때문에

삭제 시 시작 지점과 관계없이 진행되어 dist는 시작 지점으로부터 최단 거리를 저장하는 것이 아니라,

음수 싸이클이 존재하는지 판단할 수 있게 된다. 

- 처음에는 모든 시작점에서부터 벨만 포드 알고리즘을 실행하고 음수 사이클이 있는지 판단하여 시간초과 발생 

# https://www.acmicpc.net/problem/1865
import sys
input = sys.stdin.readline 

def bf(start):
    dist = [INF] * (n+1)
    # 자기 자신까지의 거리 0 으로 초기화
    dist[start] = 0 
    for i in range(n):
        # 매 반복마다 모든 간선 확인 
        for edge in edges:
            # 현재 노드 
            node = edge[0]
            # 다음 노드 
            next_node = edge[1]
            # 가중치
            cost = edge[2]
            # 현재 노드를 거쳐 다른 노드로 이동하는 거리가 더 짧을 경우 
            if dist[next_node] > dist[node] + cost:
                # 갱신
                dist[next_node] = dist[node] + cost
                # n-1 번 이후 반복에도 값이 갱신된다면 음수 순환 존재 
                if i == n-1:
                    return True
    return False 
    
test = int(input())
INF = int(1e9)
for _ in range(test):
    n, m, w = map(int,input().split())
    
    edges = []

    for _ in range(m):
        a, b, c = map(int,input().split())
        edges.append((a,b,c))
        edges.append((b,a,c))
        
    for _ in range(w):
        a, b, c = map(int,input().split())
        edges.append((a,b,-c))
    # 시작 지점은 상관없음 
    cycle = bf(1)
    # 음수 사이클이 존재하면 
    if cycle:
        print('YES')
    else:
        print('NO')