BOJ:9466基準項目**


1


https://suri78.tistory.com/128を参照
サイクルはvisitに置かれたgroupの数字で区切られます.
while visit[i] == 0:
  visit[i] = group
  i = choice[i]
→接続されたインデックスのvisit[index]に同じ値のgroup数を加えます.
他のグループまたは現在のグループに接続されているノードに遭遇した場合は、巡視を停止します.
while visit[i] == group:
  visit[i] = -1
  i = choice[i]
→最後のインデックス値からループの再検索を開始します.
現在groupに属しているノードで関連する値を検索します.
cnt = 0
for v in visit:
	if v > 0:
	cnt += 1
→相互接続のノードはvisit=-1なのでvisit!=一人の個数を調べる.
num_test = int(sys.stdin.readline())

for _ in range(num_test):
    n = int(sys.stdin.readline())
    choice = [0] + list(map(int, list(sys.stdin.readline().strip().split())))
    visit = [0] * (n + 1)

    group = 1
    for i in range(1, n+1):
        if visit[i] == 0:
            while visit[i] == 0:
                visit[i] = group
                i = choice[i]
            while visit[i] == group:
                visit[i] = -1
                i = choice[i]
            group += 1
    cnt = 0
    for v in visit:
        if v > 0:
            cnt += 1
    print(cnt)

2


https://claude-u.tistory.com/435を参照
import sys
sys.setrecursionlimit(111111) #충분한 재귀 깊이를 주어 오류를 예방


def dfs(x):
    global result
    visited[x] = True
    cycle.append(x) #사이클을 이루는 팀을 확인하기 위함
    number = numbers[x]
    
    if visited[number]: #방문가능한 곳이 끝났는지
        if number in cycle: #사이클 가능 여부
            result += cycle[cycle.index(number):] #사이클 되는 구간 부터만 팀을 이룸
        return
    else:
        dfs(number)


for _ in range(int(input())):
    N = int(input())
    numbers = [0] + list(map(int, input().split()))
    visited = [True] + [False] * N #방문 여부
    result = []
    
    for i in range(1, N+1):
        if not visited[i]: #방문 안한 곳이라면
            cycle = []
            dfs(i) #DFS 함수 돌림
            
    print(N - len(result)) #팀에 없는 사람 수