[BaekJoon 1976 : Graph Search, Python] - 여행가자 (dfs ver.)

2021, Dec 06    


백준 여행가자 : 골드 4



Solution


import sys
sys.setrecursionlimit(10000000)
input = sys.stdin.readline
from collections import defaultdict

n, k = int(input()), int(input())
graph = defaultdict(list)
for i in range(n):      # row
    tmp = list(map(int, input().split()))
    for j in range(n):       # col
        if tmp[j] == 1:
            graph[i+1].append(j+1)

flag = False
def dfs(s, d, visited):       # dfs
    global flag
    if s == d:
        return True
    if flag:
        return True
    for v in graph[s]:
        if v not in visited:
            if v == d:
                flag = True
                return True
            else:
                visited.append(v)
                dfs(v, d, visited)
    return flag  

travel = list(map(int, input().split()))

if len(travel) == 1:            # 여행할 도시가 1개뿐일 때
    if travel[0] > n:           # 주어진 도시 범위 밖의 여행지이면 NO
        print("NO")
    else:
        print("YES")
    sys.exit(0)

for k in range(len(travel)-1):
    visited = [travel[k]]
    flag = False
    res = dfs(travel[k], travel[k+1], visited)      # 매 경로마다 가능한지 여부 확인
    if not res:
        print("NO")
        break
else:
    print("YES")     


풀이과정 및 느낀점


이 문제를 처음 봤을 때 가장 처음 떠오른 방법은 dfs 또는 bfs 를 활용하는 방법이었다.
여행경로 리스트(1-5-4-2-3)를 받아서 각각의 여행경로(1-5) 마다 실현가능한지 확인하는 dfs 함수를 짜고 한 번이라도 불가능한 경로가 나오면 NO 를 출력했다.

예외처리할 때 주의할 부분은

  1. 여행지 자체가 1개뿐일 때는 for 문을 타지 못하기 때문에 따로 처리를 해줘야 한다.
  2. 시작과 끝, 즉 (1->1) 이런 경로는 내 코드 상에서 visited 에 걸려 False 가 나오기 때문에 이 경우도 따로 함수 시작에 처리해줬다.

우선 이렇게 풀어서 정답이 나오긴 했지만, 시간이 1400ms 정도나 걸렸는데 다른 사람들 풀이를 보니 100ms 미만이었다.
참고해보니 Union-Find 알고리즘을 사용해서 시작과 도착경로가 동일한 집합 내에 속해있는지 여부를 따지면서 푼 듯했다.
다음에는 동일한 문제를 유니온 파인드 알고리즘을 활용해서 풀이한 문제를 올릴 예정이다.