DFS 문제이다. 트리가 주어지며, 각 노드는 실외/실내의 특성을 갖는다.
산책 루트는 반드시 실내로 시작해서 실내로 끝나야 한다. 그 사이에 실외가 몇개 있든 상관 없다. 이러한 산책 루트가 최대 몇개인지를 출력하면 되는 문제이다. 방향만 바꾼 것도 포함이다. 1->3 , 3->1 이 루트는 별개의 루트이다.
처음엔 문제 지문 그대로 코드로 옮겨 풀었었다.
처음에 푼 코드다.
- 모든 실내 노드를 시작 지점으로 삼아 DFS를 진행했다.
- 진행 중 다른 실내 노드를 만난다면 즉시 return하고 result를 1개 추가했다.
- 진행 중 다른 실외 노드를 만난다면 DFS를 재귀호출했다.
문제 지문을 그대로 코드로 옮겨 적은 코드이다. 다만 이렇게 풀면 정답은 나오는데 "시간 초과"가 뜬다. 정확히는 73점이 나왔다. 5개 케이스 중 3개는 통과, 2개는 시간 초과.
모든 실내 노드에 대해서 연산을 진행하는게 비효율적인 것 같다. 방향만 바꾼 경로도 추가 연산을 해 줘야 하기도 하고...
조금 더 효율적인 방법이 필요했다.
두번째로 푼 코드다.
- 모든 실외 노드를 기준으로 DFS를 진행하여, 인접한 실내 노드 개수(num)를 파악한다.
- num * (num - 1) 공식을 이용해 result에 모든 경로의 수를 합산해준다.
- 실내 노드끼리 연결된 경우는 입력받을 때 if문을 통해 예외처리하여 result에 경로 2개를 추가한다.
실내 노드가 아닌 실외 노드를 기준으로 탐색했다. 그 이유는 실외 노드를 기준으로 경로의 개수를 찾는 기가막힌 공식이 있기 때문이다.
특정 실외 노드와 인접한 실내 노드의 개수를 N이라고 했을 때, 해당 실외 노드를 거치는 모든 경로의 수는 N * (N - 1) 이다. 내가 이 공식을 수학적으로 증명하진 못하겠지만 어쨌든 그렇다. 따라서 트리의 모든 경로의 수를 구하는 방법은, 모든 실외 노드에 대하여 이 공식을 적용하고 그것을 전부 더하면 된다.
다만 여기서 추가적인 예외상황이 발생하는데, 바로 실내 노드끼리만 연결되어 있을 경우이다. 2개의 실내 노드가 연결되어 있다면 이것은 경로 2개로 계산해주면 된다. 입력받을 때 바로 체크해주면 되겠다. 3개 이상의 실내 노드는 연결될 수 없다. 정확히는 연결되어도 그게 경로가 될 수 없다. 어차피 실내 노드를 만나면 진행이 끊기니까 3개까지 못 가는 것이다. 그러므로 연결된 2개의 실내 노드에 대해서만 처리를 해 주면 모든 예외상황을 처리할 수 있다.
그리고 sys.setrecursionlimit(10 ** 6) 꼭 해줘야 한다. 최대 재귀호출 한계를 설정해 주는 코드인데 이걸 안 해주면 통과가 안된다.
'Algorithm > DFS' 카테고리의 다른 글
[Baekjoon 2668 / Python / 골드5] 숫자고르기 (0) | 2024.10.05 |
---|---|
[Baekjoon 11724 / python / 실버2] 연결 요소의 개수 (0) | 2024.03.30 |
[Baekjoon 11725 / python / 실버2] 트리의 부모 찾기 (2) | 2024.03.30 |
[Baekjoon 2606 / python / 실버3] 바이러스 (0) | 2024.03.30 |
[Baekjoon 1260 / python / 실버2] DFS와 BFS (0) | 2024.03.29 |