Algorithm/Problem Solving
[BOJ/GoldIV] 2056. 작업 - JAVA 자바
gangintheremark
2024. 4. 24. 20:47
728x90
2056번: 작업
수행해야 할 작업 N개 (3 ≤ N ≤ 10000)가 있다. 각각의 작업마다 걸리는 시간(1 ≤ 시간 ≤ 100)이 정수로 주어진다. 몇몇 작업들 사이에는 선행 관계라는 게 있어서, 어떤 작업을 수행하기 위해
www.acmicpc.net
- 592ms
- 위상정렬
어떤 작업을 수행하기 전 반드시 선행되어야 하는 작업이 존재한다. 작업의 시간과 선행관계가 주어졌을 때, 모든 작업을 완료하기 위해 필요한 최소시간을 구하는 문제이다.
선행관계 + 사이클이 없는 방향그래프 ➜ 위상정렬 !!
큐를 이용한 위상 정렬 알고리즘
- 진입차수가 0인 모든 노드를 큐에 넣는다.
- 큐가 빌 때까지 다음의 과정 반복
- 큐에서 원소를 꺼내 해당 노드에서 나가는 간선을 그래프에서 제거
- 진입차수가 0이 된 노드를 큐에 넣기
⇒ 결과적으로 각 노드가 큐에 들어온 순서가 위상 정렬을 수행한 결과와 같다.
import java.io.*;
import java.util.*;
public class Main {
static int n;
static int[] indegree;
static Node[] graph;
static class Node implements Comparable<Node> {
int time;
ArrayList<Integer> list;
public Node(int time) {
this.time = time;
list = new ArrayList<>();
}
@Override
public int compareTo(Node o) {
return this.time - o.time;
}
}
public static int topologySort() {
int time = 0;
PriorityQueue<Node> pq = new PriorityQueue<Node>();
for (int i = 1; i <= n; i++) {
if (indegree[i] == 0)
pq.offer(graph[i]);
}
while (!pq.isEmpty()) {
Node now = pq.poll();
time = now.time;
for (int i = 0; i < now.list.size(); i++) {
int work = now.list.get(i);
indegree[work]--; // 진입차수-1
if (indegree[work] == 0) {
graph[work].time += now.time;
pq.offer(graph[work]);
}
}
}
return time;
}
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
n = Integer.parseInt(br.readLine());
indegree = new int[n + 1];
graph = new Node[n + 1];
// 작업에 걸리는 시간과 선행 관계
for (int i = 1; i <= n; i++) {
st = new StringTokenizer(br.readLine());
graph[i] = new Node(Integer.parseInt(st.nextToken()));
int tmp = Integer.parseInt(st.nextToken());
for (int j = 0; j < tmp; j++) {
graph[Integer.parseInt(st.nextToken())].list.add(i);
indegree[i]++; // 진입차수+1
}
}
int result = topologySort();
System.out.println(result);
}
}
728x90