ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 9466번 텀 프로젝트
    문제 풀이 2020. 4. 2. 00:05

    9466 텀 프로젝트


    문제


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

    학생들이(s1, s2, ..., sr)이라 할 때, r=1이고 s1이 s1을 선택하는 경우나, s1이 s2를 선택하고, s2가 s3를 선택하고,..., sr-1이 sr을 선택하고, sr이 s1을 선택하는 경우에만 한 팀이 될 수 있다.

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


    입력


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


    출력


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


    풀이)


    재귀적 방법을 통해 사이클이 생겼으면 팀으로 묶는 방법을 사용했다.

    처음에 main()에서 각 학생에 대한 재귀 함수를 호출할 때, 학생이 이미 사이클에 속하는지 아닌지 확인했던 걸 체크해주지 않았더니

    각 학생마다 재귀를 돌면서, 시간초과가 일어났다.

    그래서 이미 확인해봤던 학생은 재귀를 돌지 않게 하면서, 다시 확인하지 않도록 해줬다.


    과정은 이러하다.

    1. 빈 vector 변수를 만든다.

    2. i*번 학생부터 함수를 통해 함께하고 싶은 학생을 확인한다.

    3. 만약 함께하고 싶은 학생이 j일때

       3.1 j가 이전에 확인했던 학생이 아닌 경우 vector에 넣어주고 j에 대한 재귀적 함수 호출한다. 2

       3.2 j가 확인했던 친구라면 vector에서 함수를 처음에 호출했던 학생 번호 i*로 사이클이 생기는 지 확인한다.

            사이클 생성되었다면, vector에서 사이클에 포함된 학생을 제외한 

            나머지 학생의 수를 어느 프로젝트 팀에도 속하지 않는 학생이라고 본다.


    코드)


    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
    #include <stdio.h>
    #include <vector>
    using namespace std;
     
    int n;
    vector <int> stu;
    bool visited[100001]; //0, 1~100000
    vector <int> test;
    int person;//팀에 속해져있는사람수
     
    void dfs(int idx) {
        if (visited[idx] == false) {    
            test.push_back(idx);
            visited[idx] = true;
            dfs(stu[idx]);
        }
        else {
            int i = 0;
            for (i; i < test.size(); i++) {
                if (test[i] == idx) break;
            }
            person += (test.size() - i);
        }
        
        
    }
     
    int main() {
        int t;
        scanf("%d"&t);
        for (int i = 0; i < t; i++) {
            scanf("%d"&n);
            stu.resize(n + 1);
            for (int j = 1; j <= n; j++) {
                scanf("%d"&stu[j]);
            }
            
            for (int j = 1; j <= n; j++) {
                if (visited[j] == false) {
                    dfs(j);
                    test.clear();
                } 
            }
            
            printf("%d\n", n - person);
     
            fill(visited, visited + n + 1false);
            person = 0;
        }
        return 0;
    }
    cs


    혹시 이해가 되지 않을까봐 문제 예시에 대한 그림을 그려봤다.

    7명의 학생이 있고, 선택의 결과가 이러하다면


    1234567
    3137346



    결과)


    '문제 풀이' 카테고리의 다른 글

    [백준] 1107번 리모컨  (0) 2020.04.03
    [백준] 1181번 단어정렬  (0) 2020.04.02
    [백준] 1182번 부분수열의 합  (0) 2020.04.01
    [백준] 1238번 파티  (0) 2020.03.31
    [백준] 2533번 사회망서비스  (0) 2020.03.31

    댓글

Designed by Tistory.