Coding Test/Solution

[C++] 2056 - 작업 (골드5)

나죽못고나강뿐 2022. 8. 5. 21:41

1. 문제 설명

 

 

2056번: 작업

수행해야 할 작업 N개 (3 ≤ N ≤ 10000)가 있다. 각각의 작업마다 걸리는 시간(1 ≤ 시간 ≤ 100)이 정수로 주어진다. 몇몇 작업들 사이에는 선행 관계라는 게 있어서, 어떤 작업을 수행하기 위해

www.acmicpc.net

 


2. 아이디어

 

이전에 음악 프로그램인가? 몇 번 접해본 유형의 문제라 위상 정렬 알고리즘을 쓰면 되겠다는 걸 금방 캐치했다.

당시에 C++을 얼마 써보지 않아서 동적할당 연습 겸 배열을 사용했는데,

나중에 SCPC에서 알게 된 거지만 배열은 크기가 100,000까지로 제한되어 있어서

벡터에 충분한 크기의 공간을 상수로 넣어주는 게 훨씬 편하다.

 

위상 정렬인 것만 알면 그 후로 로직 자체는 간단하다.

선행 조건이 없는 작업부터 큐에 담고 하나씩 빼면서 이후 작업의 진입 차수를 1씩 제거하면

쉽게 답을 얻어낼 수 있다.

 


3. 코드

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

using namespace std;

int main(void) { // 전형적인 위상 정렬 문제
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);

    int n; cin >> n;

    vector<int> graph[10001];
    int* indegree = new int[n+1];
    int* cost = new int[n+1];
    int result[10001];
    int t, m;

    for (int i=0; i < n+1; i++) {
        indegree[i] = 0;
        cost[i] = 0;
        result[i] = 0;
    }

    for (int i = 1; i < n+1; i++) {
        cin >> t >> m;

        cost[i] = t;
        for (int j = 0; j < m; j++) {
            int node;
            cin >> node;
            graph[node].push_back(i);
            indegree[i]++;
        }
    }

    priority_queue<int> queue;

    for (int i = 1; i < n+1; i++) {
        if (indegree[i] == 0) {
            queue.push(i);
            result[i] = cost[i];
        }
    }

    int tmp;
    while (!queue.empty()) {
        tmp = queue.top();
        queue.pop();
        for (auto i : graph[tmp]) {
            indegree[i]--;
            if (indegree[i] == 0) {
                queue.push(i);
            }
            if (result[i] < result[tmp] + cost[i]) {
                result[i] = result[tmp] + cost[i];
            }
        }
    }

    sort(result, result + n + 1);
    cout << result[n];

    return 0;
}