Post

[백준] 9466번: 텀 프로젝트

[백준] 9466번: 텀 프로젝트

📌 문제

https://www.acmicpc.net/problem/9466

📌 설명

DFS 를 통해 사이클을 찾는 방법을 사용하는 문제이다.

image.png

위 그림에서 A, B, C는 팀 생성이 불가능하며, 나머지는 팀 생성이 가능하다. DFS의 시작 노드를 start, DFS 수행 중 이미 방문한 노드를 처음 만났을 때 해당 노드를 cur 이라고 한다면, start 부터 cur 이전까지는 팀 생성이 불가능하다. 단, startcur이 같은 경우는 본인이 본인을 선택하는 경우이므로, 그냥 넘어간다.

📌 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>

using namespace std;

int arr[100001];
int visited[100001]; // 0: 방문X, 1: 팀 생성 가능, -1: 팀 생성 불가능
int n, start;

void dfs(int i) {
	// 순환: x에서 시작, y가 순환의 시작 => x부터 y 전까지 visited를 -1로 변경
	// 단 x와 y와 같은 경우 pass
	// 순환 발생 여부: 접근하려고 하는 사람이 이미 방문한(y) 경우

	if (visited[i]) {
		if (i == start)
			return;
		while (start != i) {
			visited[start] = -1;
			start = arr[start];
		}
		return;
	}

	visited[i] = 1;
	dfs(arr[i]);
}

int main() {
	cin.tie(0);
	ios::sync_with_stdio(0);

	int T;
	cin >> T;
	while (T--) {
		cin >> n;
		for (int i = 1;i <= n;i++) {
			cin >> arr[i];
		}

		for (int i = 1;i <= n;i++) {
			start = i;
			if (visited[i] == 0) {
				dfs(i);
			}
		}

		int cnt = 0;
		for (int i = 1;i <= n;i++) {
			if (visited[i] != 1)
				cnt++;
			visited[i] = 0;
		}

		cout << cnt << "\n";
	}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import sys
input=sys.stdin.readline
sys.setrecursionlimit(10**6)

def dfs(cur,start,arr,visited):
    # 이미 방문한 경우
    if visited[cur]:
        # 본인이 본인을 선택한 경우
        if cur==start:
            return
        
        # start부터 cur 이전까지는 팀 생성 불가능
        while start!=cur:
            visited[start]=-1
            start=arr[start]

        return
    
    visited[cur]=1
    dfs(arr[cur],start,arr,visited)

T = int(input())

for _ in range(T):
    n=int(input())
    arr = [0] + list(map(int, input().split()))

    # 0: 방문 X, 1: 팀 생성 가능, -1: 팀 생성 불가능
    visited=[0]*(n+1)

    for i in range(1, n+1):
        if visited[i]==0:
            start=i
            dfs(i,start,arr,visited)

    cnt=0
    for i in range(1, n+1):
        if visited[i]!=1:
            cnt+=1

    print(cnt)
This post is licensed under CC BY 4.0 by the author.