문제링크 :https://www.acmicpc.net/problem/9466

 

9466번: 텀 프로젝트

문제 이번 가을학기에 '문제 해결' 강의를 신청한 학생들은 텀 프로젝트를 수행해야 한다. 프로젝트 팀원 수에는 제한이 없다. 심지어 모든 학생들이 동일한 팀의 팀원인 경우와 같이 한 팀만

www.acmicpc.net

 문제설명 

 

1. 학생의 수가 주어지고  각 학생이 팀을이루고 싶은 사람을 지목한다

2. 서로 지목을 하거나 지목한 사람끼리 사이클을 이룬다면 팀을 이룰 수있다.

3. 팀을 이루지 못한 사람의 수를 출력

 

 알고리즘 

 

1. 재귀함수 를 이용하여 컴포넌트의 수를 구하는데 ,, 

 

2. done 배열을 이용하여 해당 노드를 더이상 방문 하지않아도 되는 것을 표시하는 한다

   - 만약 해당 학생이 이미 사이클을 이룬다면 더이상 방문 하지 않아도됨.

 

3. 방문한적이 있는데(visited[i] = 1) 끝난 노드(done[i]=0)가 아니다 ->사이클을 이룬다

   - 사이클을 이루면 해당 사이클의 인원수를 세어준다 . (for문을 이용하는데 코드 꼭 참고 개중요)

 

4. 팀을 이루지 못한 사람의 수를 출력.

 

 코드 

 

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
57
58
59
60
61
#include<iostream>
 
using namespace std;
 
int N, cnt;
int line[100001];
bool visited[100001];
bool done[100001]; // 방문종료 여부
 
void DFS(int node) {
 
    visited[node] = 1;
    int next = line[node];
    //방문한적이없으면 재귀
    if (!visited[next]) DFS(next);
    
    //방문한적이 있는데 끝난노드가 아니다.->사이클을이룸
    else if (!done[next]) {
        
        
        //팀원의 수를샘 , for문 중요
        for (int i = next; i != node; i = line[i])cnt++;
 
        cnt++;
 
    }
    done[node] = 1;
}
 
void reset(int num) {
    for (int i = 0; i < num; i++) {
        visited[i] = 0;
        line[i] = 0;
        done[i] = 0;
    }
}
int main() {
 
    int T;
    cin >> T;
 
    for (int i = 0; i < T; i++) {
        cin >> N;
        reset(N);
 
        for (int j = 1; j <= N; j++) {
            cin >> line[j];
        }
 
        //팀을이룬사람의수
        cnt = 0;
 
        for (int j = 1; j <= N; j++) {
            if (!visited[j])
                DFS(j);
        }
 
        //팀을이루지못한 사람의수
        cout << N - cnt << endl;
    }
}
cs

 

참고한 블로그 : https://jaimemin.tistory.com/674

ariz1623