[ 백준 ] 2056 / 작업

金弘均·2021년 9월 14일
0

Baekjoon Online Judge

목록 보기
6/228
post-thumbnail

# Appreciation

/*
 * Problem :: 2056 / 작업
 *
 * Kind :: Dynamic Programming + Data Structure
 *
 * Insight
 * - 어떤 작업 x 가 끝났을 때, 그 x 를 선행 작업으로 가지고 있는 작업들에게
 *   어떻게 x 라는 작업이 끝났음을 알려줄 수 있을까?
 *   + 굳이 x 라는 작업이 끝났음을 알려주어야 할까?
 *     작업 y 가 있고 선행 작업으로 x 를 가지고 있다고 할 때,
 *     작업 y 의 총 선행 작업들의 개수를 n 개라고 하면
 *     x 가 끝났을 때 이 n 을 감소시켜서 n 이 0 이 되었을 때 작업을 실행시켜주면 되지 않을까?
 *     # 작업을 실행시켰을 때 끝나는 시간까지 고려해주고
 *       우선순위 큐를 활용해서 현재 실행중인 작업들 중 가장 빨리 끝나는 작업을 찾고
 *       그 작업을 선행 작업으로 가지고 있는 작업들을 갱신시켜준다면... 풀수있겠다!
 *
 * Point
 * - 1번 작업 외에도 선행 작업이 하나도 없는 작업이 있을 수 있다!
 *   + 총 선행 작업들의 개수가 0 개인 작업들을 동시에 실행시켜주자
 */

# Code

//
//  BOJ
//  ver.C++
//
//  Created by GGlifer
//
//  Open Source

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

using namespace std;

#define endl '\n'

// Set up : Global Variables
struct Operation { int no, t; };

// Set up : Functions Declaration
bool operator < (const Operation &u, const Operation &v);


int main()
{
    // Set up : I/O
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    // Set up : Input
    int N; cin >> N;
    int T[N+1]; vector<int> K[N+1]; int C[N+1];
    for (int i=1; i<=N; i++) {
        cin >> T[i];
        int n; cin >> n;
        C[i] = n; /* i 번 작업의 총 선행 작업들의 개수는 n 개 */
        for (int j=0; j<n; j++) {
            int no; cin >> no;
            K[no].push_back(i); /* no 번 작업은 i 번 작업을 선행 작업으로 가짐 */
        }
    }

    // Process
    priority_queue<Operation> pq;
    for (int i=1; i<=N; i++) {
        if (C[i] == 0) { /* 선행 작업이 하나도 없는 작업들을 우선순위 큐에 추가 */
            pq.push({i, T[i]});
        }
    }

    int ans = -1;
    while (not(pq.empty())) {
        auto [c, t] = pq.top(); /* 실행중인 작업들 중
                                 * 가장 빨리 끝나는 작업의 번호(c)와 그 때 시간(t) */
        pq.pop();

        for (int n : K[c]) { /* c 번 작업을 선행 작업으로 가지고 있는 작업(n)들 순회 */
            C[n]--; /* n 번 작업의 실행되어야 할 선행 작업들의 총 개수 감소 */
            if (C[n] == 0) { /* 실행되어야 할 선행 작업들이 하나도 없다면 */
                pq.push({n, t+T[n]}); /* 우선순위 큐에 추가 */
            }
        }

        if (pq.empty()) {
            ans = t; /* 마지막 작업이 끝나는 시간 */
        }
    }

    // Control : Output
    cout << ans << endl;
}

// Helper Functions
bool operator < (const Operation &u, const Operation &v)
/* Operation 구조체의 최소힙 정렬을 위한 연산자 오버로딩 */
{
    return make_pair(u.t, u.no) > make_pair(v.t, v.no);
}
profile
이런 미친 게임을 봤나! - 옥냥이

0개의 댓글