사용자 도구

사이트 도구


ps:problems:programmers:67260

동굴 탐험

ps
링크programmers.co.kr/…
출처프로그래머스
문제 번호67260
문제명동굴 탐험
레벨Level 4
분류

그래프, 사이클 찾기

시간복잡도O(n)
인풋사이즈n<=200,000
사용한 언어Python
해결날짜2020/12/23

풀이

  • 유향 그래프에서 사이클의 존재 여부를 찾는 문제의 변형.
  • 주어지는 그래프는 트리이다
    • 문제의 “임의의 서로 다른 두 방 사이의 최단경로는 딱 한 가지만 있으며” 라는 조건은 트리가 아니라도 성립할 수 있다. 트리의 조건이 되려면, '최단경로'가 '단순경로'로 바뀌어야 한다
    • 대신, 모든 동굴이 연결되어 있고, 패스의 개수가 n-1개라는 것이 트리의 조건이 된다.
  • 루트에서부터 이동할 때, 차일드 노드를 첫 방문하기 위해서는 그 부모 노드를 방문해야 한다. 따라서, 무향 그래프를 부모 노드에서 자식 노드로 가는 엣지만 존재하는 유향 그래프라고 생각해도 상관 없다.
  • 결국, 이러한 유향그래프에 order에서 주어지는 엣지들을 추가해서 만든 그래프가, 사이클을 포함하는지를 찾는 문제이다.
  • 풀 수 있는 방법은 여러가지이다. 다 O(E)에 풀린다. O(E) = O(|path| + |order|) = O(n)
    • 간단하게 떠오르는 것은 DFS나 BFS를 한번 돌려서 유향 그래프로 변환한 후에, 기본적인 사이클 검출 알고리즘을 쓰는 방법도 가능하다.
      • 기본적인 사이클 검출 알고리은 DFS에 기반한 방식과 Kahn의 위상정렬 알고리즘에 기반한 방식이 있다.
    • 아니면, 유향그래프로 변환하는 과정 없이, 사이클 검출 알고리즘을 약간 변형해서 바로 돌리는 것도 가능하다.
      • Kahn의 위상정렬 알고리즘을 사용할 때에는, 각 노드의 in-degree의 갯수를 세는 과정만 달라진다. 트리이기 때문에, 루트 노드를 제외한 모든 노드는 부모노드로부터만 들어오는 엣지가 있으므로 in-degree는 굳이 엣지들의 갯수를 세며 계산할 필요 없이 그냥 1이다. 인접한 노드들중 어느 노드가 부모노드이고 어느 노드가 자식 노드인지를 굳이 알 필요가 없다. 이 편이 원래 알고리즘 코드를 변형할 부분이 적어보여서 이 방식으로 구현했다
      • DFS로 사이클을 찾을때에는, 이동할때 path의 엣지로 이동하는지 order의 엣지로 이동하는지에 따라, path의 엣지로 이동할 때에는 그 역방향 엣지를 지워주면 된다. 구현은 안해봤다.
  • 빼먹기 쉬운 테스트 케이스는, order중에 A방을 방문한 다음 0번 방을 방문해야 하는 것이 있는 경우. 이 경우는 진입 자체를 못하니까 불가능, False를 리턴해야한다

코드

"""Solution code for "Programmers 67260. 동굴 탐험".

- Problem link: https://programmers.co.kr/learn/courses/30/lessons/67260
- Solution link: http://www.teferi.net/ps/problems/programmers/67260
"""


def solution(n, path, order):
    graph = [[] for _ in range(n)]
    indegrees = [1] * n
    indegrees[0] = 0
    for u, v in path:
        graph[u].append(v)
        graph[v].append(u)
    for u, v in order:
        graph[u].append(v)
        indegrees[v] += 1

    if indegrees[0] > 0:
        return False
    stack = [0]
    visited_room_count = 0
    while stack:
        u = stack.pop()
        visited_room_count += 1
        for v in graph[u]:
            indegrees[v] -= 1
            if indegrees[v] == 0:
                stack.append(v)

    return visited_room_count == n

토론

댓글을 입력하세요:
R J W T X
 
ps/problems/programmers/67260.txt · 마지막으로 수정됨: 2020/12/23 15:44 저자 teferi