[백준] 11725번 트리의 부모 찾기 | 파이썬 Python

문제

루트 없는 트리가 주어진다. 이때, 트리의 루트를 1이라고 정했을 때, 각 노드의 부모를 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 노드의 개수 N (2 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N-1개의 줄에 트리 상에서 연결된 두 정점이 주어진다.

 

출력

첫째 줄부터 N-1개의 줄에 각 노드의 부모 노드 번호를 2번 노드부터 순서대로 출력한다.

 

예제

 

DFS, BFS란?

  DFS (Depth-First Search) BFS (Breadth-First Search)
탐색 방식 깊이 우선 탐색 너비 우선 탐색
경로 탐색 깊은 곳까지 탐색 후 백트래킹 (뒤로가기) 가까운 노드부터 차례로 탐색
구현 방식 스택(Stack) or 재귀(Recursion) 큐(Queue)
메모리 사용 낮음 (경로 저장 필요 없음) 높음 (경로 저장 필요)
사용 예시 백트래킹 문제, 미로 찾기, 순열/조합 최단 거리 탐색, 네트워크 문제

 

풀이1 (DFS - 재귀)

import sys
sys.setrecursionlimit(10**6)
input = sys.stdin.readline

N = int(input())
graph = [[] for _ in range(N+1)]

for i in range(N-1):
    A, B = map(int, input().split())
    graph[A].append(B)
    graph[B].append(A)

visited = [0]*(N+1)

def dfs(s):
    for i in graph[s]:
        if visited[i] == 0:
            visited[i] = s
            dfs(i)

dfs(1)

for i in range(2, N+1):
    print(visited[i])
  • 루트 노드인 `1`부터 시작해서 경로를 따라 트리 깊숙이 들어간다. DFS는 항상 부모 노드에서 자식 노드로 이동한다는 점이 이 풀이의 핵심이다.
  • `visited[i] == 0`이라면, 즉 해당 노드에 처음 방문하는 것이라면 `s`라는 부모 노드를 통해 방문한 것이 되므로 `visited[i] = s`로 교체한다.

 

풀이2 (DFS - 스택)

import sys
input = sys.stdin.readline

N = int(input())
graph = [[] for _ in range(N+1)]

for i in range(N-1):
    A, B = map(int, input().split())
    graph[A].append(B)
    graph[B].append(A)

visited = [0]*(N+1)

def dfs(node):
    stack = [node]

    while stack:
        top = stack.pop()

        for i in graph[top]:
            if visited[i] == 0:
                visited[i] = top
                stack.append(i)

dfs(1)

for i in range(2, N+1):
    print(visited[i])
  • `1`부터 시작해서 스택에 노드를 삽입, 삭제하면서 하나씩 내려가면서 탐색한다.

 

풀이3 (BFS - 큐)

import sys
input = sys.stdin.readline
from collections import deque

N = int(input())
graph = [[] for _ in range(N+1)]

for i in range(N-1):
    A, B = map(int, input().split())
    graph[A].append(B)
    graph[B].append(A)
    
visited = [0]*(N+1)

def bfs(start):
    queue = deque([start])

    while queue:
        node = queue.popleft()

        for i in graph[node]:
            if visited[i] == 0:
                visited[i] = node
                queue.append(i)
        
bfs(1)

for i in range(2, N+1):
    print(visited[i])
  • 큐에서 `popleft()`로 노드를 가져오게 되면 트리 구조의 상단에 위치한 노드부터 탐색하게 되면서 BFS가 실행된다.

 

회고

  • 처음 DFS, BFS로 풀어본 문제라 개념과 풀이 방법을 이해하는데 시간이 걸렸다.
  • 처음부터 너무 완벽하게 모든 것을 이해하려고 하지 말고 알고리즘마다 어떤 구현 방식을 사용하는지, 그리고 그 구현 방식의 흐름을 파악하기 위해 노력했다.

 

참고