관리 메뉴

SW

[백준 9466] 텀 프로젝트 본문

대학교/Algorithm

[백준 9466] 텀 프로젝트

SWKo 2020. 2. 13. 12:24

0. 제목

  • 백준 9466 텀 프로젝트
  • BOJ 9466 텀 프로젝트
  • C++ 9466 텀 프로젝트

1. 문제

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


2. 풀이

  • 문제에서 프로젝트를 함께 하고 싶은 학생을 단 한 명만 선택할 수 있다고 하였다.
  • 그렇기 때문에 vector를 이용할 필요가 없고 connect라는 배열을 선언해서 해결이 가능하다.
  • connect[2] = 3; 의 의미는 2번 학생이 3번 학생을 가리키고 있다는 것이다.
  • done은 이미 방문하였고 더 이상 볼 필요가 없는 점들을 표시하는 배열이다.
  • visited는 방문 여부를 체크하는 배열이다.
  • 먼저 여기서 dfs 함수는 사이클을 체크하는 함수로 쓰인다. 이 함수에 대해 설명해보면 다음과 같다.
  • 처음에 방문하므로 visited[x] = true 이고 y는 x에 연결된 학생번호를 가리킨다.
  • 만약 연결된 학생이 방문하지 않은 점이었다면 재귀적으로 다시 dfs(y)를 한다. 하지만, 방문했을 경우 사이클체크가 완료되었는지 확인한다.
  • 사이클 즉, done배열에 포함이 되어 있지 않으면 그 연결된 점부터 자기 자신으로 돌아오기 하나 전까지 반복하면서 개수를 센다.
  • 반복문이 완료되면 자기 자신도 포함 시켜야 하므로 개수에 1을 더해준다.
  • 모든 루프에서 조건문이 끝나면 done[x] = true; 즉, 더이상 볼 필요 없는 배열의 값에 true를 넣어준다.
  • 1->2->3->1  이 사이클로 예를 들어보면, 1에서 시작하면 dfs(1)을 수행한다. visited[1] = true 가 되고 y는 2가 된다. 2는 방문한적없으니 dfs(2)를 한다. 똑같이 visited[2] = true가 되고 y = 3이 된다. dfs(3)을 실시한다. visited[3] = true가 되고 y = 1 이 된다.
  • y는 이미 방문 한 배열이므로 else구문을 실행하게 된다. done[1] = false 이며 for 문을 살펴보면 다음과 같다.
  • for(i = 1; i != 3; i = connect[i])   이것은 i = 1 부터 연결된 점을 따라가다가 3이 되면 탈출하는 것이다. 연결된 점을 따라가면서 개수를 세고 반복문을 탈출하게 되면 i==3 일때 개수를 안세주었기 때문에 개수에 1을 더해준다.
  • 그 후 done[3] = true를 하고 재귀를 사용했으므로 나머지 done[2] = true , done[1] = true를 해준다.
  • main함수를 보면 매번 케이스마다 배열 3개를 0과 false로 초기화해준다. 그리고 1부터 n까지 반복하면서 방문하지 않은 점이라면 그 점부터 dfs를 실시한다.
  • 그렇게 센 개수들을 모든 점의 개수인 n에서 뺀다. 그럼 어느 프로젝트 팀에도 속하지 않는 학생들의 수가 나온다.

3. 코드

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
#include <iostream>
#include <cstring>
using namespace std;
 
int connect[100001];//화살표가 한방향으로 가기때문에 vector대신 배열 사용가능
bool done[100001];
bool visited[100001];
int T, n, cnt;
 
void dfs(int x){
    visited[x] = true;
    int y = connect[x];
    if(!visited[y])
        dfs(y);
    else{
        if(!done[y]){
            for(int i = y; i != x; i = connect[i]){//
                cnt++;//연결된 점들 개수 세기
            }
            cnt++;//자기 자신
        }
    }
    done[x] = true;
}
 
int main(int argc, const char * argv[]) {
    cin >> T;
    for(int i = 0; i < T; i++){
        cin >> n;
        
        cnt = 0;
        memset(connect, 0sizeof(connect));
        memset(done, falsesizeof(done));
        memset(visited, falsesizeof(visited));
        
        for(int j = 1; j <= n; j++){
            cin >> connect[j];
        }
        for(int j = 1; j <= n; j++){
            if(!visited[j])
                dfs(j);
        }
        
        cout << n - cnt << '\n';
    }
    return 0;
}

'대학교 > Algorithm' 카테고리의 다른 글

[백준 2751] 수 정렬하기 2  (0) 2020.02.13
[백준 2667] 단지번호붙이기  (0) 2020.02.13
[백준 2579] 계단 오르기  (0) 2020.02.09
[백준 10610] 30  (0) 2020.02.08
[백준 2875] 대회 or 인턴  (0) 2020.02.07
Comments