알고리즘/[ Baekjoon ]

[ Baekjoon ][JAVA][2056] 작업

kim.svadoz 2020. 9. 12. 13:22
반응형

www.acmicpc.net/problem/2056

 

2056번: 작업

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

www.acmicpc.net

문제

수행해야 할 작업 N개 (3 ≤ N ≤ 10000)가 있다. 각각의 작업마다 걸리는 시간(1 ≤ 시간 ≤ 100)이 정수로 주어진다.

몇몇 작업들 사이에는 선행 관계라는 게 있어서, 어떤 작업을 수행하기 위해 반드시 먼저 완료되어야 할 작업들이 있다. 이 작업들은 번호가 아주 예쁘게 매겨져 있어서, K번 작업에 대해 선행 관계에 있는(즉, K번 작업을 시작하기 전에 반드시 먼저 완료되어야 하는) 작업들의 번호는 모두 1 이상 (K-1) 이하이다. 작업들 중에는, 그것에 대해 선행 관계에 있는 작업이 하나도 없는 작업이 반드시 하나 이상 존재한다. (1번 작업이 항상 그러하다)

모든 작업을 완료하기 위해 필요한 최소 시간을 구하여라. 물론, 서로 선행 관계가 없는 작업들은 동시에 수행 가능하다.

입력

첫째 줄에 N이 주어진다.

두 번째 줄부터 N+1번째 줄까지 N개의 줄이 주어진다. 2번째 줄은 1번 작업, 3번째 줄은 2번 작업, ..., N+1번째 줄은 N번 작업을 각각 나타낸다. 각 줄의 처음에는, 해당 작업에 걸리는 시간이 먼저 주어지고, 그 다음에 그 작업에 대해 선행 관계에 있는 작업들의 개수(0 ≤ 개수 ≤ 100)가 주어진다. 그리고 선행 관계에 있는 작업들의 번호가 주어진다.

출력

첫째 줄에 모든 작업을 완료하기 위한 최소 시간을 출력한다.

예제입력

image-20200912131450579

예제출력

image-20200912131557361

코드

위상정렬문제로 입력을 통해 DAG를 만들고, 각 작업들의 indegree값을 구해야 한다. 또한 각 작업들에 소요되는 시간도 저장해야 한다.

 

처음 indegree가 0인 정점들을 q에 push한 뒤 위상정렬을 수행한다.

 

주의할 점은 queue에서 pop된 작업과 연결되어 수행될작업을 끝내기 위해 소요되는 시간은 최대값이 되도록 해야한다.

package baekjoon;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;

public class Work_2056 {
	static int N;
    static int[] indegree, times;
    static List<Integer>[] list;
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
 
    public static void main(String[] args) throws IOException {
 
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
 
        times = new int[N + 1];
        indegree = new int[N + 1];
        list = new ArrayList[N + 1];
 
        for (int i = 1; i <= N; i++)
            list[i] = new ArrayList<>();
 
        for (int i = 1; i <= N; i++) {
            st = new StringTokenizer(br.readLine());
 
            times[i] = Integer.parseInt(st.nextToken());
            int work = Integer.parseInt(st.nextToken());
 
            for (int j = 0; j < work; j++) {
                int preWork = Integer.parseInt(st.nextToken());
                list[preWork].add(i);
                indegree[i] += 1;
            }
        }
        topologySort();
    }
 
    public static void topologySort() {
 
        int[] result = new int[N + 1];
        Queue<Integer> q = new LinkedList<>();
 
        for (int i = 1; i <= N; i++) {
 
            if (indegree[i] == 0) {
                q.offer(i);
                result[i] = times[i];
            }
        }
 
        for (int i = 1; i <= N; i++) {
 
            if (q.isEmpty()) {
                System.out.println("사이클 발생");
                return;
            }
 
            int node = q.poll();
 
            for (int j = 0; j < list[node].size(); j++) {
 
                int adj = list[node].get(j);
 
                if (result[adj] < times[adj] + result[node])
                    result[adj] = times[adj] + result[node];
                
                indegree[adj] -= 1;
                if (indegree[adj] == 0) {
                    q.offer(adj);
                }
 
            }
        }
        Arrays.sort(result);
        System.out.println(result[N]);
    }

}
반응형