문제링크 : https://www.acmicpc.net/problem/2056
2056번: 작업
수행해야 할 작업 N개 (3 ≤ N ≤ 10000)가 있다. 각각의 작업마다 걸리는 시간(1 ≤ 시간 ≤ 100)이 정수로 주어진다. 몇몇 작업들 사이에는 선행 관계라는 게 있어서, 어떤 작업을 수행하기 위해
www.acmicpc.net
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MAX = 987654321;
vector<int>inDegree, v, result;
vector<vector<int>>graph;
int N, num, task, ans;
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> N;
result.resize(N+1);
v.resize(N+1);
inDegree.resize(N+1);
graph.resize(N+1);
for(int i=1; i<=N; i++)
{
cin >> v[i] >> num;
for(int j=0; j<num; j++)
{
cin >> task;
graph[task].push_back(i);
inDegree[i]++; //진입 차수 증가
}
}
queue<int>q;
for(int i=1; i<=N; i++) //진입차수가 0인 정점들을 큐에 삽입
{
if(inDegree[i]==0) q.push(i);
result[i]=v[i];
}
for(int i=0; i<N; i++)
{
if(q.empty()) break; //큐가 비면 사이클 발생이므로 종료
int cur = q.front(); //현재 방문 노드
q.pop();
ans = max(result[cur], ans);
for(int j=0; j<graph[cur].size(); j++) //인접한 노드들의 진입 차수를 1씩 줄이고, 0이면 다시 큐에 삽입
{
int next = graph[cur][j];
result[next] = max(result[next], result[cur] + v[next]); //작업시간 갱신
if(--inDegree[next]==0) q.push(next);
}
}
cout << ans;
return 0;
}
위상정렬 문제의 응용문제이다.
위상정렬에 대한 내용은 어제 작성했었으므로 이번 문제에서는 스킵하였다.
참고링크 : https://blob-thinking.tistory.com/281
[백준 2252번] 줄 세우기 (C++)
문제링크 : https://www.acmicpc.net/problem/2252 2252번: 줄 세우기 첫째 줄에 N(1 ≤ N ≤ 32,000), M(1 ≤ M ≤ 100,000)이 주어진다. M은 키를 비교한 회수이다. 다음 M개의 줄에는 키를 비교한 두 학생의 번호 A, B
blob-thinking.tistory.com
해당 문제에서 추가로 고려해야할 것은 작업 순서에 따른 작업시간 갱신이다.
<작업 순서 : 1 2 4 3 5 6 7>
cur : 1, next = 2
작업시간(result[next]) : max(1, 5 + 1) = 6
cur : 1, next = 4
작업시간(result[next]) : max(6, 5 + 6) = 11
cur : 2, next = 3
작업시간(result[next]) : max(3, 6 + 3) = 9
cur : 2, next = 5
작업시간(result[next]) : max(1, 6 + 1) = 7
cur : 2, next = 6
작업시간(result[next]) : max(8, 6 + 8) = 14
cur : 4, next = 5
작업시간(result[next]) : max(7, 11 + 1) = 12
cur : 4, next = 6
작업시간(result[next]) : max(14, 11 + 8) = 19
cur : 3, next = 7
작업시간(result[next]) : max(4, 19 + 4) = 13
cur : 5, next = 7
작업시간(result[next]) : max(13, 12 + 4) = 16
cur : 6, next = 7
작업시간(result[next]) : max(16, 19 + 4) = 23
result[next] = max(result[next], result[cur] + v[next] 해당 수식을 통해서 작업시간을 갱신해준다.
기본적으로 현재 작업시간 + 다음 작업시간을 더해주는데,
해당 작업에 도달하는 경로가 여러가지 이므로 최대 작업시간으로 갱신해준다.
문제에서 "K번 작업에 대해 선행 관계에 있는(즉, K번 작업을 시작하기 전에 반드시 먼저 완료되어야 하는) 작업들의 번호는 모두 1 이상 (K-1) 이하"라고 써져있기 때문에,
최대 작업시간으로 갱신해야 선행 관계에 있는 작업을 모두 완료한 상태인 것을 알 수 있다.
마찬가지로 결과값을 출력 할때도 result배열의 최대값을 출력해줘야 정답이다.
'백준 > 골드' 카테고리의 다른 글
[백준 4781번] 사탕 가게 (C++) (0) | 2023.09.28 |
---|---|
[백준 7579번] 앱 (C++) (0) | 2023.09.27 |
[백준 2252번] 줄 세우기 (C++) (0) | 2023.09.25 |
[백준 2143번] 두 배열의 합 (C++) (0) | 2023.09.23 |
[백준 2473번] 세 용액 (C++) (0) | 2023.09.21 |