Coding Test/BaekJoon_Python

백준 2637 <장난감 조립> Python

JunOnJuly 2025. 1. 16. 15:33
728x90

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


위상정렬 문제입니다.

 

간단하게 생각해보면 DFS 나 BFS 를 사용해 한 부품씩 곱해 더해주면 될 것 같지만 단계나 부품의 수가 복잡해지고 배수가 늘어나면 시간이나 메모리가 부족해집니다. 그렇기에 조금 더 효율적으로 단계를 진행할 필요가 있습니다.

 

그렇기에 단계별로 개수를 병합해 한번에 곱하는 식으로 진행하면 비교적 효율적으로 진행할 수 있습니다.

위 방법으로 진행할 때 모든 중간부품의 개수를 카운트하지 않았을 때 다음 단계를 계산해버리면 오류가 생기므로 중간부품의 개수가 모두 카운트 될 때 다음 단계로 넘어가야 하는데, 이 때 위상정렬을 사용할 수 있습니다.

 

B 부품을 만들기 위해 A 부품이 필요하다고 할 때(A->B) 'B 부품 노드에 A 부품 노드가 들어오는 노드다' 라고 표현하겠습니다. 들어오는 노드의 수가 양수면 아직 해당 부품의 개수를 모두 카운트 하지 않았기에 큐에 넣지 않고 들어오는 노드의 수가 0 이면 해당 부품의 개수를 모두 카운트했다고 생각할 수 있으므로 다음 노드를 큐에 넣어줄 수 있습니다.


import sys
from collections import deque

input = sys.stdin.readline


def solution(N, M, gears):
    # 그래프
    graph = [[] for _ in range(N+1)]
    for x, y, k in gears:
        graph[x].append([y, k])
    
    # 위상 정렬 그래프 / [들어오는 노드의 수, 나가는 노드의 수]
    topol_list = [[0, 0] for _ in range(N+1)]
    topol_list[0] = [float('inf'), float('inf')]
    for parent, child, _ in gears:
        topol_list[parent][1] += 1
        topol_list[child][0] += 1

    # 필요한 부품의 수
    gears = [0 for _ in range(N+1)]
    gears[N] = 1
    # 큐
    q = deque([N])
    # 순회
    while q:
        # 현재 노드
        now_node = q.popleft()
        # 순회
        for next_node, mul in graph[now_node]:
            # 부품의 수 더해주기
            gears[next_node] += gears[now_node] * mul
            # 다음 노드의 들어오는 노드 빼주기
            topol_list[next_node][0] -= 1
            # 다음 노드의 들어오는 노드가 0 이면 큐에 넣어주기
            if not topol_list[next_node][0]:
                q.append(next_node)
    
    for gear in range(len(gears)):
        if not topol_list[gear][1]:
            print(f'{gear} {gears[gear]}')


# 입력
N = int(input().strip())
M = int(input().strip())
gears = [list(map(int, input().strip().split())) for _ in range(M)]

solution(N, M, gears)

 

728x90