C++ 코딩테스트 강좌, 선분 방향 구하기

코딩테스트는 현업에서의 프로그래밍 능력을 평가하기 위해 다양한 문제를 포함하고 있습니다. 이번 글에서는 C++로 ‘선분의 방향 구하기’ 문제를 해결하는 과정을 자세히 알아보겠습니다. 이 문제는 기하학적 문제로, 점과 벡터의 기초적인 개념이 필요합니다.

문제 설명

주어진 점 A(x1, y1), B(x2, y2), C(x3, y3)가 있을 때, 선분 AB와 선분 AC의 방향을 구하는 문제입니다. 이때 선분의 방향은 시계 방향, 반시계 방향 또는 동일선 위로 구분됩니다.

입력 형식

3
0 0
1 1
2 2

첫 번째 줄에는 점의 개수가 주어지고, 다음 세 줄에는 각각 점의 좌표가 주어집니다.

출력 형식

0

0은 동일선 위에 있음을 나타내며, 1은 반시계 방향, -1은 시계 방향을 의미합니다.

알고리즘 접근법

세 점 A, B, C가 주어졌을 때 그들의 방향성은 벡터의 외적을 통해 구할 수 있습니다. A에서 B로 향하는 벡터와 A에서 C로 향하는 벡터의 외적의 부호를 이용하여 방향을 결정할 수 있습니다.

벡터의 외적 계산

외적을 통해 구한 결과는 다음과 같이 정의됩니다:

cross_product = (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1)

여기서:

  • cross_product > 0 : 반시계 방향
  • cross_product < 0 : 시계 방향
  • cross_product = 0 : 동일선 위

코드 구현

이제 C++로 문제를 해결하기 위한 코드를 작성해 보겠습니다.

#include <iostream>

using namespace std;

int main() {
    int x1, y1, x2, y2, x3, y3;
    
    // 점 A, B, C의 좌표 입력
    cout << "점 A 좌표 (x1 y1): ";
    cin >> x1 >> y1;
    cout << "점 B 좌표 (x2 y2): ";
    cin >> x2 >> y2;
    cout << "점 C 좌표 (x3 y3): ";
    cin >> x3 >> y3;

    // 외적 계산
    int cross_product = (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1);
    
    // 방향 판단
    if (cross_product > 0) {
        cout << "반시계 방향 (1)" << endl;
    } else if (cross_product < 0) {
        cout << "시계 방향 (-1)" << endl;
    } else {
        cout << "동일선 위 (0)" << endl;
    }

    return 0;
}

코드 설명

코드는 다음과 같은 단계를 포함합니다:

  1. 사용자로부터 점 A, B, C의 좌표를 입력받습니다.
  2. 외적을 계산하여 cross_product를 구합니다.
  3. 결과에 따라 방향을 판단하고 출력합니다.

보다 심화된 이해를 위한 추가 설명

이 문제는 기하학적 이해를 요구합니다. 벡터의 외적은 일반적으로 3D 공간에서 두 벡터의 평면을 구별하는 데 사용되지만, 2D 공간에서는 방향을 구별하는 데 유용한 도구となります. 기하학적 개념과 벡터 수학을 이해하므로써, 다양한 문제를 해결할 능력을 기를 수 있습니다.

기하학적 직관

기하학적으로 이 문제는 직선의 기울기를 이해하는 것이기도 합니다. 선분 A에서 B로, 그리고 A에서 C로 향하는 경우, 두 벡터의 상대적인 기울기를 판단함으로써 방향성을 파악 할 수 있습니다. cross_product가 양수인지 음수인지에 따라 점 C가 선 AB의 왼쪽에 있는지 오른쪽에 있는지를 알 수 있습니다.

결론

이번 강좌에서는 간단한 기하학 문제를 통해 코딩테스트에서 자주 출제되는 유형을 다뤘습니다. ‘선분의 방향 구하기’ 문제는 기초적인 기하학의 이해가 필요한 문제로, 벡터의 외적을 이용하여 해결할 수 있습니다. 이러한 문제를 연습함으로써 알고리즘적 사고를 기르고, 기초적인 C++ 프로그래밍 능력을 향상시킬 수 있습니다.

참고: 이 문제는 다양한 변형으로 실전에서 많이 출제됩니다. 예를 들어, N개의 점이 주어졌을 때, 다각형의 방향성 판단 문제로 확장될 수 있습니다. 이러한 문제를 통해 기하학 알고리즘을 계속 연습하시기 바랍니다.

C++ 코딩테스트 강좌, 선물 전달하기

안녕하세요, 여러분! 이번 포스팅에서는 C++ 알고리즘 문제로 “선물 전달하기”라는 주제를 다뤄보겠습니다. 이 문제는 특히 순차적 사고와 알고리즘 디자인 능력을 시험하는 데 초점이 맞춰져 있습니다.

문제 설명

선물 전달하기 문제는 여러 명이 있는 그룹에서 선물을 상호 간에 전달하는 과정을 모델링했습니다. 여러분은 다음의 조건을 갖춘 문제를 해결해야 합니다.

  • n명의 사람들이 있습니다.
  • 각 사람은 한 개의 선물을 가집니다.
  • 어떤 두 사람은 서로에게 선물을 전달할 수 있습니다.

여러분의 목표는 모든 사람이 최소한 한 개의 선물을 받도록 선물을 최적으로 전달하는 방법을 찾는 것입니다.

입력 형식

첫 번째 줄에 사람의 수 n이 주어지며, 다음 n개의 줄에는 각 사람이 가지고 있는 선물의 정보가 주어집니다.

출력 형식

모든 사람이 적어도 하나의 선물을 받는 최소한의 선물 전달 방법을 출력합니다.

접근 방법

이번 문제를 해결하기 위해서는 그래프 이론의 기초와 BFS 또는 DFS와 같은 탐색 알고리즘에 대한 이해가 필요합니다. 문제를 해결하기 위한 전략은 다음과 같습니다:

  1. 문제를 그래프 형태로 모델링하기
  2. BFS 또는 DFS를 이용하여 선물 전달 경로 탐색하기
  3. 각 노드(사람)에서 최소 경로를 찾아 선물 전달하기

C++ 코드 구현

이제 본격적으로 C++ 코드를 통해 문제를 해결해 보겠습니다. 아래 코드는 주어진 조건을 바탕으로 사람들 간의 선물 전달을 구현한 예제입니다.

            
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

struct Person {
    int id;
    vector<int> gifts;
};

// 선물 전달을 위한 선 그래프
void giftExchange(vector<Person> &people) {
    queue<int> q;
    vector<bool> received(people.size(), false);

    // 처음 선물을 받지 못한 사람을 찾아 큐에 넣음
    for (int i = 0; i < people.size(); ++i) {
        if (people[i].gifts.empty()) {
            q.push(i);
        }
    }

    while (!q.empty()) {
        int current = q.front();
        q.pop();
        
        for (int giftRecipient : people[current].gifts) {
            if (!received[giftRecipient]) {
                cout << "사람 " << current << "이(가) 사람 " << giftRecipient << "에게 선물을 전달하였습니다!" << endl;
                received[giftRecipient] = true;
                // 선물을 전달한 후 현재 사람을 다시 큐에 추가
                q.push(giftRecipient);
            }
        }
    }
}

int main() {
    int n;
    cout << "사람의 수를 입력하세요: ";
    cin >> n;
    vector<Person> people(n);

    for (int i = 0; i < n; ++i) {
        people[i].id = i;
        int m;
        cout << "사람 " << i << " 이(가) 주는 선물의 수를 입력하세요: ";
        cin >> m;

        for (int j = 0; j < m; ++j) {
            int giftRecipient;
            cout << "사람 " << i << " 이(가) 전달할 선물 받는 사람의 ID 입력: ";
            cin >> giftRecipient;
            people[i].gifts.push_back(giftRecipient);
        }
    }

    giftExchange(people);
    return 0;
}
            
        

코드 설명

위의 코드는 선물 전달 문제를 해결하기 위한 C++ 프로그램을 구현합니다. 각 사람은 자신의 선물 목록을 가지고 있으며, 큐를 사용하여 전달 과정을 시뮬레이션합니다. 선물을 한 번도 받지 못한 사람부터 시작하여, 각 사람이 전달하는 선물을 적절히 시뮬레이션하는 방식입니다.

코드 분석

코드를 차례대로 분석해 보겠습니다:

  • 구조체 정의: struct Person는 사람의 ID와 그 사람이 전달할 선물의 정보를 저장합니다.
  • 큐 초기화: 선물을 받지 못한 사람을 찾아 큐에 추가합니다.
  • 반복문: 큐에서 사람을 하나씩 꺼내고, 해당 사람이 보유한 선물을 전달하는 과정을 진행합니다.

주요 개념 해설

이 문제를 통해 다음과 같은 알고리즘 개념을 이해할 수 있습니다:

  • BFS 탐색: 너비 먼저 탐색(Breadth-First Search) 알고리즘을 사용하여 선물 전달 과정을 시뮬레이션합니다.
  • 그래프 모델링: 사람과 선물 전달 관계를 그래프 형태로 모델링하여 문제를 효율적으로 해결합니다.

문제 해결 후 생각할 점

문제를 해결한 후, 다음과 같은 질문들을 스스로에게 해보세요:

  • 이 알고리즘의 시간 복잡도는 얼마인가요?
  • 다른 접근 방법이 있었나요?
  • 이 문제를 변형하여 응용해볼 수 있는 다른 문제는 어떤 것들이 있을까요?

결론

코딩테스트 준비에는 다양한 문제를 경험하고 알고리즘 설계 능력을 키우는 것이 중요합니다. “선물 전달하기” 문제를 통해 DFS와 BFS 방식으로 그래프 탐색을 익힐 수 있었기를 바랍니다. C++ 언어의 특징을 잘 활용하여 효율적인 코드를 작성하는 연습도 게을리하지 마세요!

다음 시간에는 또 다른 흥미로운 문제를 가지고 오겠습니다. 감사합니다!

C++ 코딩테스트 강좌, 삽입 정렬

안녕하세요! 이번 포스트에서는 C++를 이용한 코딩테스트에서 자주 출제되는 알고리즘 중 하나인 삽입 정렬에 대해 다뤄보겠습니다. 삽입 정렬은 매우 직관적인 정렬 알고리즘으로, 정렬된 배열에 새로운 데이터를 삽입하는 방식으로 동작합니다. 그럼 시작해볼까요?

문제 설명

주어진 정수를 포함한 배열이 있습니다. 이 배열을 삽입 정렬을 이용해 오름차순으로 정렬한 결과를 출력하시오.

입력 형식

첫 번째 줄에 배열의 크기 N이 주어집니다. (1 ≤ N ≤ 1000)

두 번째 줄에 N개의 정수가 공백으로 구분되어 주어집니다. (각 정수는 -1000 ≤ x ≤ 1000)

출력 형식

정렬된 배열을 한 줄에 출력하시오. 각 요소는 공백으로 구분됩니다.

예제

        입력:
        5
        3 2 1 5 4
  
        출력:
        1 2 3 4 5
    

알고리즘 설명

삽입 정렬(Insertion Sort)은 정렬된 배열에 새로운 값을 삽입하는 방식으로 동작합니다. 알고리즘은 다음과 같은 단계로 진행됩니다:

  1. 첫 번째 원소는 정렬된 배열로 간주합니다.
  2. 두 번째 원소부터 시작하여 해당 원소를 정렬된 배열에 삽입할 위치를 찾습니다.
  3. 배열의 원소를 오른쪽으로 한 칸씩 이동시키면서 새 원소가 들어갈 위치를 찾습니다.
  4. 올바른 위치를 찾으면 새 원소를 삽입합니다.
  5. 이 과정을 배열의 모든 원소에 대해 반복합니다.

C++ 코드 구현

이제 위의 알고리즘을 C++로 구현해보겠습니다. 코드는 다음과 같습니다:

        
        #include <iostream>
        #include <vector>

        using namespace std;

        void insertionSort(vector<int>& arr) {
            int n = arr.size();
            for (int i = 1; i < n; i++) {
                int key = arr[i];
                int j = i - 1;

                // key보다 큰 원소들을 한 칸씩 이동
                while (j >= 0 && arr[j] > key) {
                    arr[j + 1] = arr[j];
                    j--;
                }
                arr[j + 1] = key; // key를 적절한 위치에 삽입
            }
        }

        int main() {
            int N;
            cin >> N;
            vector<int> arr(N);

            for (int i = 0; i < N; i++) {
                cin >> arr[i];
            }

            insertionSort(arr);

            for (int i = 0; i < N; i++) {
                cout << arr[i];
                if (i < N - 1) cout << " "; // 마지막 원소 뒤에 공백을 추가하지 않기 위해
            }

            return 0;
        }
        
    

코드 설명

위 코드는 삽입 정렬 알고리즘을 C++로 구현한 것입니다. 주요 부분을 살펴보겠습니다:

  • 헤더 파일 포함: <iostream>와 <vector>를 포함하여 입력 및 출력을 수행하고 동적 배열을 사용할 수 있도록 합니다.
  • insertionSort 함수: 배열을 정렬하는 함수입니다. 각 원소에 대해 키를 설정하고 정렬된 배열에 삽입할 위치를 찾습니다.
  • 메인 함수: 정렬할 배열의 크기를 입력받고, 배열을 입력받은 후 insertionSort 함수를 호출하여 정렬합니다. 최종적으로 정렬된 결과를 출력합니다.

시간 복잡도 분석

삽입 정렬의 시간 복잡도는 다음과 같습니다:

  • 최악의 경우: O(n^2) (배열이 뒤죽박죽일 때)
  • 평균 경우: O(n^2)
  • 최선의 경우: O(n) (배열이 이미 정렬되어 있을 때)

이러한 시간 복잡도로 인해 삽입 정렬은 작은 배열에 대해 효율적이지만, 큰 배열에 대해서는 성능이 떨어집니다.

장단점

장점

  • 코드 구현이 간단하고 이해하기 쉬움
  • 작은 데이터 세트에 대해서는 매우 효율적
  • 안정 정렬입니다 (같은 값을 가진 요소들의 순서가 유지됨)

단점

  • 시간 복잡도가 O(n^2)로 큰 입력 데이터에 대해 효율적이지 않음
  • 배열을 직접 수정하기 때문에 메모리 사용이 비효율적일 수 있음

이해도를 높이기 위한 추가 예제

추가적인 예제를 통해 삽입 정렬의 동작을 시각적으로 이해해보겠습니다. 다음은 삽입 정렬의 과정을 보여주는 예제입니다.

예제

        입력:
        6
        4 3 5 1 2 6
  
        과정:
        초기 배열: 4 3 5 1 2 6
        1단계: [4] [3] 5 1 2 6 → 3 4 5 1 2 6
        2단계: 3 4 [5] [1] 2 6 → 3 4 5 1 2 6
        3단계: 3 4 5 [1] [2] 6 → 1 3 4 5 2 6
        4단계: 1 3 4 5 [2] 6 → 1 2 3 4 5 6
        5단계: 1 2 3 4 5 [6] → 1 2 3 4 5 6
        

결론

오늘은 C++를 이용한 삽입 정렬에 대해 알아보았습니다. 삽입 정렬은 간단하면서도 유용한 알고리즘으로, 작은 데이터 세트에서는 효과적이라는 점을 기억해두세요. 다음 포스트에서는 보다 복잡한 정렬 알고리즘인 퀵 정렬에 대해 다룰 예정입니다. 질문이나 코멘트가 있으면 아래에 남겨주세요. 감사합니다!

참고 자료

C++ 코딩테스트 강좌, 사전 찾기

안녕하세요! 오늘은 C++을 이용한 알고리즘 문제를 하나 해결해보는 시간을 가지겠습니다. 이번 주제는 “사전 찾기”입니다. 이 문제는 주어진 단어 목록에서 특정 단어를 찾는 과정을 다루고 있습니다. 이와 관련된 알고리즘을 함께 살펴보면서, 어떻게 효율적으로 문제를 해결할 수 있는지 알아보겠습니다.

문제 설명

주어진 문제는 다음과 같습니다.

    문제: 사전에서 단어 찾기
    - n개의 단어로 이루어진 사전이 주어집니다.
    - 입력으로 검색할 단어가 주어질 때, 이 단어가 사전에 존재하는지 확인하는 프로그램을 작성하세요.
    
    입력:
    - 첫 번째 줄에 단어의 개수 n(1 ≤ n ≤ 100,000)이 주어집니다.
    - 다음 n개의 줄에 각각 알파벳 소문자로 구성된 단어가 주어집니다.
    - 마지막 줄에 검색할 단어가 주어집니다.
    
    출력:
    - 검색할 단어가 사전에 존재하면 'YES', 그렇지 않으면 'NO'를 출력합니다.
    

문제의 분석

이 문제는 단순한 문자열 검색 문제로, 사전에서 단어를 찾는 것입니다. 따라서 해결해야 할 주요 포인트는 효율적인 검색 방법입니다. 주어진 단어의 수가 최대 100,000개에 달하기 때문에, 비효율적인 방법으로는 시간 초과가 발생할 수 있습니다.

가장 간단한 방법은 리스트를 이용해 모든 단어를 순회하며 값을 비교하는 것이지만, 이 방법은 시간 복잡도가 O(n)으로, 최악의 경우 최적의 성능을 요구하는 경량 검색엔진에서는 비효율적입니다. 그러므로 해시맵을 이용한 방법이 필요합니다. 해시맵을 사용하면 평균적으로 O(1)의 시간 복잡도로 검색이 가능해지기 때문입니다.

구현 방법

이제 본격적으로 문제를 해결하기 위해 C++로 코드를 작성해보겠습니다. 아래의 절차로 진행합니다:

  1. 단어의 개수를 입력받습니다.
  2. 단어들을 저장하기 위해 unordered_map을 사용하여 해시맵을 구성합니다.
  3. 사전에 있는 단어를 해시맵에 추가합니다.
  4. 검색할 단어를 입력받고 해시맵에서 해당 단어의 존재 여부를 확인합니다.

코드 구현

    
    #include 
    #include 
    #include 

    using namespace std;

    int main() {
        int n;
        cin >> n; // 단어 개수 입력
        unordered_map dictionary; // 해시맵 초기화

        // 단어 입력
        for (int i = 0; i < n; i++) {
            string word;
            cin >> word;
            dictionary[word] = true; // 단어를 해시맵에 추가
        }

        string searchWord;
        cin >> searchWord; // 검색할 단어 입력

        // 단어 존재 여부 확인
        if (dictionary.find(searchWord) != dictionary.end()) {
            cout << "YES" << endl; // 존재할 경우
        } else {
            cout << "NO" << endl; // 존재하지 않을 경우
        }

        return 0;
    }
    
    

코드 설명

코드를 간단히 설명하겠습니다.

  • #include <iostream>: C++에서 입력과 출력을 위한 라이브러리를 포함합니다.
  • #include <unordered_map>: 해시맵을 사용하기 위한 라이브러리입니다. 이로 인해 O(1)의 시간 복잡도로 검색할 수 있습니다.
  • #include <string>: 문자열을 다루기 위한 라이브러리입니다.
  • unordered_map dictionary;: 단어를 저장할 해시맵을 선언합니다.
  • cin >> n;: 단어의 개수를 입력받습니다.
  • dictionary[word] = true;: 입력받은 단어를 해시맵에 추가합니다. 해시맵의 키는 단어, 값은 true로 설정합니다.
  • dictionary.find(searchWord): 검색어를 해시맵에서 찾아 존재 여부를 확인합니다.

테스트 및 결과

이제 실제로 이 코드를 테스트해 보겠습니다. 예를 들어, 다음과 같은 입력을 해보겠습니다:

    5
    apple
    banana
    cherry
    date
    elderberry
    banana
    

위와 같이 입력하면 출력 결과는 다음과 같습니다:

    YES
    

또 다른 예를 생각해 볼 수 있습니다:

    5
    apple
    banana
    cherry
    date
    elderberry
    fig
    

이 경우 출력 결과는 다음과 같습니다:

    NO
    

복잡도 분석

이 알고리즘의 시간 복잡도는 다음과 같습니다:

  • 단어 삽입: O(1) (평균적으로, 해시맵의 특성에 따라)
  • 단어 검색: O(1) (마찬가지로 평균적으로)

따라서 전체 시간 복잡도는 O(n)입니다. 공간 복잡도는 해시맵에 저장된 단어의 개수에 따라 O(n)입니다.

결론

오늘은 C++을 사용하여 사전에서 단어를 찾는 문제를 해결하는 방법을 알아보았습니다. 해시맵을 이용한 접근 방식이 시간 복잡도를 크게 개선할 수 있음을 보여주었습니다. 알고리즘 문제는 항상 다양한 방법으로 접근할 수 있으니, 여러 가지 방법을 시도해 보시길 바랍니다!

C++ 코딩테스트 강좌, 빌딩 순서 구하기

문제 설명

여러 개의 빌딩이 하나의 도시를 구성하고 있습니다. 각 빌딩은 고유한 번호를 가지고 있으며,
빌딩들 사이에는 방향성이 있는 도로가 존재합니다. 문제는 이러한 빌딩들을 특정한 순서로
건축해야 하는 규칙이 존재하며, 그 순서를 구하는 것입니다.

모든 빌딩은 주어진 조건에 의해 건축 순서가 결정됩니다. 이 문제는 위상 정렬(Topological Sort) 문제로
나타낼 수 있습니다. 주어진 규칙을 기반으로 원하는 빌딩의 순서를 계산하여 출력하는 것이
목적입니다.

입력 형식

첫 번째 줄에는 빌딩의 수 N과 도로의 수 M이 주어집니다. (1 ≤ N ≤ 10^6, 0 ≤ M ≤ 10^6)
다음 M개의 줄에는 도로의 정보가 주어지며, 두 정수 A, B가 주어질 경우 이는 빌딩 A가
빌딩 B보다 먼저 건축되어야 함을 의미합니다.

출력 형식

빌딩의 건축 순서를 한 줄로 출력합니다. 만약 건축 순서를 정할 수 없는 경우 ‘0’을 출력합니다.

예제

입력

    4 2
    1 2
    2 3
    

출력

    1 2 3 4
    

접근 방법

이 문제를 해결하기 위해 우리는 두 가지 방법을 고려할 수 있습니다.
1. DFS(Depth-First Search)를 활용한 방법
2. Kahn의 알고리즘을 활용한 방법

위상 정렬 문제는 사이클이 없는 방향 그래프에서 가능한 빌딩 순서를 찾아야 하는 문제입니다.
여기서 사이클이 존재하면 문제의 요구사항을 만족할 수 없기 때문에,
이를 체크하는 과정이 필요합니다.

1. DFS를 활용한 방법

DFS를 사용하여 그래프를 탐색하면서 각 노드를 방문하는 방식으로
위상 정렬을 수행할 수 있습니다. 이 방식의 핵심은 각 노드를 스택에
추가할 때, 해당 노드의 모든 자식 노드가 방문되었을 때입니다.

2. Kahn의 알고리즘

Kahn의 알고리즘은 각 노드의 진입 차수를 사용하여 위상 정렬을 수행하는 방법입니다.
이 알고리즘은 다음과 같은 단계를 포함합니다:

  1. 그래프의 진입 차수를 계산합니다.
  2. 진입 차수가 0인 노드를 큐에 추가합니다.
  3. 큐에서 노드를 하나씩 꺼내어 출력하고, 해당 노드와 연결된 모든 노드의
    진입 차수를 감소시킵니다. 만약 진입 차수가 0이 된 노드를 큐에 추가합니다.
  4. 이 과정을 반복합니다. 모든 노드를 방문했다면 성공적으로 위상 정렬을
    수행한 것이고, 사이클이 없는 것입니다.

구현

이제 위에 설명한 Kahn의 알고리즘을 사용하여 문제를 해결하는 코드를
구현해보겠습니다.


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

void topologicalSort(int N, vector>& graph, vector& inDegree) {
    queue q;
    vector result;

    // 진입 차수가 0인 노드를 큐에 추가
    for (int i = 1; i <= N; i++) {
        if (inDegree[i] == 0) {
            q.push(i);
        }
    }

    while (!q.empty()) {
        int current = q.front();
        q.pop();
        result.push_back(current);

        // 현재 노드와 연결된 모든 노드의 진입 차수 감소
        for (int neighbor : graph[current]) {
            inDegree[neighbor]--;
            if (inDegree[neighbor] == 0) {
                q.push(neighbor);
            }
        }
    }

    // 결과 출력
    if (result.size() == N) {
        for (int i = 0; i < result.size(); i++) {
            cout << result[i] << " ";
        }
        cout << endl;
    } else {
        cout << "0" << endl; // 사이클이 존재할 경우
    }
}

int main() {
    int N, M;
    cin >> N >> M;

    vector> graph(N + 1);
    vector inDegree(N + 1, 0);

    for (int i = 0; i < M; i++) {
        int A, B;
        cin >> A >> B; // A -> B
        graph[A].push_back(B);
        inDegree[B]++;
    }

    topologicalSort(N, graph, inDegree);

    return 0;
}
    

결론

위상 정렬 문제는 많은 알고리즘 문제에서 접할 수 있는 유형 중 하나로,
특히 프로젝트의 작업 순서를 결정해야 할 때 유용하게 사용될 수 있습니다.
이 강좌에서는 Kahn의 알고리즘을 통해 빌딩 순서를 구하는 문제를 해결했습니다.
다양한 변형 문제가 존재하므로, 실제 코딩테스트에서 실력을 쌓기 위해
다양한 문제를 풀어보기를 권장합니다.

수고하셨습니다! 여러분의 코딩테스트 준비에 많은 도움이 되었기를 바랍니다.