Problem Solving/항해99
99클럽 코테 스터디 12일차 TIL + DFS
wrathlion
2024. 11. 9. 02:39
문제
- 설명: 1자, 8자, 도넛 그래프가 주어지고 이 모든 그래프와 연결되는 노드 1개가 주어질 때 이 노드와 1자, 8자, 도넛 그래프의 개수를 구하라
풀이
- 각 그래프의 내차수(indegree), 외차수(outdegree)의 관점에서 생각해보자
- 기본적으로 내차수가 0이고 외차수가 2이면 모든 그래프와 연결된 노드이다.
- 1자 그래프의 시작점은 내차수가 0이고 외차수가 1개 이하이다.
- 8자 그래프의 중간점은 외차수가 2개이다.
- 이외는 도넛 그래프이다.
- 따라서 모든 그래프와 연결된 노드를 가장 먼저 구해주고, 1자, 8자 그래프의 시작점을 구한 뒤, 이 점에서 탐색을 하며 만난 노드들을 지워준다
- 마지막으로 탐색을 한적 없는 노드는 모두 도넛 그래프이다.
- 추가적으로 8자 그래프는 단순 DFS를 하면 한쪽 방향밖에 탐색할 수 없으므로 두 방향 모두 탐색해준다.
오늘의 회고
- 아무리 해도 맞게 구현했는데 python의 재귀 한계에 도달해서 런타임 에러가 발생했다.
sys.setrecurionlimit
을 노드의 최대인 $10^6$으로 설정해주어 해결했다.- 디폴트 값은 $1,000$이다.
Code
# Programmers258711.py
import sys
sys.setrecursionlimit(10 ** 6)
MAX_NODE = 1_000_001
visited = [False] * MAX_NODE
adj_list = [[] for _ in range(MAX_NODE)]
def dfs(curr):
if adj_list[curr]:
next_node = adj_list[curr][0]
if not visited[next_node]:
visited[next_node] = True
dfs(next_node)
def solution(edges):
ans = [0, 0, 0, 0]
n = 0
is_node = [False] * MAX_NODE
indegree, outdegree = [0] * MAX_NODE, [0] * MAX_NODE
for u, v in edges:
n = max(n, u, v)
is_node[u] = True
is_node[v] = True
adj_list[u].append(v)
outdegree[u] += 1
indegree[v] += 1
for i in range(1, n + 1):
if indegree[i] == 0 and outdegree[i] >= 2:
ans[0] = i
for adj in adj_list[i]:
indegree[adj] -= 1
break
stick, graph8 = [], []
for i in range(1, n + 1):
if is_node[i] and indegree[i] == 0 and outdegree[i] <= 1:
stick.append(i)
elif indegree[i] == 2 and outdegree[i] == 2:
graph8.append(i)
for i in stick:
visited[i] = True
dfs(i)
ans[2] += 1
for i in graph8:
visited[i] = True
visited[adj_list[i][0]] = True
visited[adj_list[i][1]] = True
dfs(adj_list[i][0])
dfs(adj_list[i][1])
ans[3] += 1
visited[ans[0]] = True
for i in range(1, n + 1):
if is_node[i] and not visited[i]:
visited[i] = True
dfs(i)
ans[1] += 1
return ans