알고리즘 풀이/백준

[백준 9466] 텀 프로젝트

mhko411 2021. 6. 1. 14:43
728x90

문제

이번 가을학기에 '문제 해결' 강의를 신청한 학생들은 텀 프로젝트를 수행해야 한다. 프로젝트 팀원 수에는 제한이 없다. 심지어 모든 학생들이 동일한 팀의 팀원인 경우와 같이 한 팀만 있을 수도 있다. 프로젝트 팀을 구성하기 위해, 모든 학생들은 프로젝트를 함께하고 싶은 학생을 선택해야 한다. (단, 단 한 명만 선택할 수 있다.) 혼자 하고 싶어하는 학생은 자기 자신을 선택하는 것도 가능하다.

주어진 선택의 결과를 보고 어느 프로젝트 팀에도 속하지 않는 학생들의 수를 계산하는 프로그램을 작성하라.

 

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스의 첫 줄에는 학생의 수가 정수 n (2 ≤ n ≤ 100,000)으로 주어진다. 각 테스트 케이스의 둘째 줄에는 선택된 학생들의 번호가 주어진다. (모든 학생들은 1부터 n까지 번호가 부여된다.)

 

출력

각 테스트 케이스마다 한 줄에 출력하고, 각 줄에는 프로젝트 팀에 속하지 못한 학생들의 수를 나타내면 된다.


접근

순환하는 노드를 찾고 이에 해당하지 않은 노드들을 최종해로 출력한다. 방문한 노드를 리스트에 추가하다가 한 번 방문한 노드를 다시 방문했을 때 해당 노드부터 마지막 노드까지를 순환하는 노드라고 판단한다.

 

구현

- 1번 학생부터 방문하지 않은 노드라면 DFS를 시작하며 graph에 노드들을 넣어준다. 

for _ in range(test_case):
    N = int(input())
    tree = [0] + list(map(int, input().split()))
    visited = [False] * (N+1)
    answer = []

    for i in range(1, N+1):
        if not visited[i]:
            graph = []
            DFS(i)

- 현재 방문한 노드를 방문 표시하고 graph에 추가한다.

- 이후 다음 방문한 노드를 꺼내서 방문하지 않았다면 재귀호출로 다음 DFS를 실행한다.

- 이미 방문했다면 graph 내에서 해당 노드의 위치를 찾고 마지막 노드까지 리스트 answer에 넣는다.

- 이미 방문한 노드를 또 방문한 것은 순환하는 그래프이기 때문에 DFS를 실행하지않고 종료한다. 

def DFS(node):
    global answer
    visited[node] = True
    graph.append(node)
    next_node = tree[node]
    if visited[next_node]:
        if next_node in graph:
            answer += graph[graph.index(next_node):]
        return
    else:
        DFS(next_node)

- 최종적으로 N에서 answer의 길이만큼 뺀 것이 최종해가 된다.


전체 코드

import sys
sys.setrecursionlimit(1000000)
input = sys.stdin.readline

test_case = int(input())

def DFS(node):
    global answer
    visited[node] = True
    graph.append(node)
    next_node = tree[node]
    if visited[next_node]:
        if next_node in graph:
            answer += graph[graph.index(next_node):]
        return
    else:
        DFS(next_node)

for _ in range(test_case):
    N = int(input())
    tree = [0] + list(map(int, input().split()))
    visited = [False] * (N+1)
    answer = []

    for i in range(1, N+1):
        if not visited[i]:
            graph = []
            DFS(i)

    print(N - len(answer))

'알고리즘 풀이 > 백준' 카테고리의 다른 글

[백준 7562] 나이트의 이동  (0) 2021.06.03
[백준 1743] 음식물 피하기  (0) 2021.06.03
[백준 10451] 순열 사이클  (0) 2021.06.01
[백준 14500] 테트로미노  (0) 2021.05.19
[백준 14890] 경사로  (0) 2021.05.16