소스코드
import sys
sys.setrecursionlimit(10**6)
input = sys.stdin.readline
N = int(input().strip()) # 정점 개수
A = [0] + list(map(int, input().strip()))
count = 0 # 가능한 서로 다른 산책 경로의 수
graph = [[] for _ in range(N + 1)]
for _ in range(N-1):
u,v = map(int, input().strip().split())
graph[u].append(v)
graph[v].append(u) # 무방향 그래프
# 경우 1 : 실내-실내 쌍인 경우
if A[u] == 1 and A[v] == 1:
count += 2
# 경우 2 : 실외 노드가 포함된 경우
visited = [False] * (N + 1)
def dfs(node):
indoor_count = 0 # 실외노드와 인접한 실내노드의 수
visited[node] = True # 방문처리
for neighbor in graph[node]:
# 실내 노드의 경우
if A[neighbor] == 1:
indoor_count += 1
elif not visited[neighbor] and A[neighbor] == 0:
# 실외노드인데 아직 방문 안 했다면
indoor_count += dfs(neighbor)
return indoor_count
# 결과 출력
for i in range(1, N+1):
if A[i] == 0 and not visited[i]:
indoor_count = dfs(i)
count += indoor_count * (indoor_count - 1)
print(count)
Python
복사
풀이
•
처음에는 실내로 시작해서 실외면 함수를 재귀호출하고, 실내 노드를 만나면 카운트를 증가시켜서 결과 처리 하는 형태로 제출했었습니다. 그렇게 할 경우, 방문 처리도 체크했다가 해제해야 다른 노드에서 해당 노드를 카운트할 수 있더라구요. 아 너무 복잡해진다 싶어서 다른 방법을 생각해봤습니다.
•
아예 (실내 - 실내) 경우와 (실외를 포함) 경우를 분리해서 고려해보면 좋겠다라고 판단했습니다. 실내끼리의 경우는 입력으로 주어지는 간선을 통해 확인하면 곧바로 결과에 반영할 수 있고, 실외가 포함된 경우만 잘 처리해주면 되겠다고 생각했습니다.
◦
실외 노드로 시작을 하는 함수입니다. 순회하면서 실외 노드를 만났을 때, 아직 방문하기 전이라면 DFS 함수를 시작합니다.
▪
방문처리를 합니다.
▪
DFS 함수에서는 인접한 실내 노드들의 개수를 구합니다. 인접 노드가 곧바로 실내라면 1을 증가합니다. 인접 노드가 실외라면 재귀 호출해서 해당 실외 노드의 인접한 실내 노드를 구해내고 이를 반영합니다.
◦
DFS 함수가 리턴한 실내 노드의 개수를 이용해 가능한 경우의 수를 구합니다(조합).
•
결과를 출력하면 끝!!
회고
•
처음에 간단하게 작성한 DFS 함수로 60점을 받은 후, 방향은 맞는 것 같은데 어딜 수정해야하지? 늪에 빠져서 허우적대다가 소모한 시간이 적지 않았습니다
. 질문을 자주 하는 것도 좋은 건 아니지만, 질문을 어느 타이밍때 해야 시간을 더 안 잡아먹고 다음으로 넘어갈 준비를 할 수 있을지 저만의 기준선을 잘 찾아봐야겠습니다.
•
경우의 수를 분리해서 다루니 DFS 함수의 로직이 복잡하지가 않더라구요. 아무튼 한 함수에서 너무 많은 일을 하고 있다면 뭔가 잘못된건가 생각해볼 필요도 있겠습니다(물론 다른 방향이 맞는 지를 고민해볼 수 있는 능력을 키워야겠죠?).
