[BOJ] 1516 : 게임 개발
풀이
위상정렬
vector v[i]는 정점i에서 나가는 정점들의 집합,
degree[i]는 정점i의 진입차수 (들어오는 간선수)
time은 정점i(번째 건물)를 건설하는데 걸리는 시간이다.
기본적인 위상정렬처럼 진입차수가 0인것부터 큐에넣은뒤 빼면서 v[i]집합안의 인덱스들에도 접근하여
해당 degree를 빼고, degree가 0이된다면 큐에 다시 넣는 방법으로 탐색한다.
하지만 이때 가장 오래걸리는 시간(임계값)을 탐색해야 되므로
ans[v[x][j]] = max(ans[x]+time[v[x][j]],ans[v[x][j]]);
코드로 계산한다. 그래프를 그림을 그려보면 이해하기 쉽다.
현재 내값과, 전에방문하는건물의 총시간+현재건물의 시간중의 큰값을 고른다.
즉, 마지막에 방문하는 건물의 총시간+현재건물의 시간이 더 커지면 갱신을 하는것이다.
코드
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
#include <queue>
using namespace std;
queue<int> q;
vector<int> v[501];
vector<int> ans(501);
int degree[501];
int time[501];
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
int tmp;
cin >> tmp;
time[i] = tmp;
cin >> tmp;
while (tmp != -1) {
v[tmp].push_back(i);
degree[i]++;
cin >> tmp;
}
}
for (int i = 1; i <= n; i++) {
if (degree[i] == 0) {
q.push(i);
ans[i] = time[i];
}
}
for (int i = 1; i <= n; i++) {
int x = q.front();
q.pop();
for (int j = 0; j < v[x].size(); j++) {
degree[v[x][j]]--;
ans[v[x][j]] = max(ans[x]+time[v[x][j]],ans[v[x][j]]);
if (degree[v[x][j]] == 0) {
q.push(v[x][j]);
}
}
}
for (int i = 1; i <= n;i++) {
cout << ans[i] << '\n';
}
return 0;
}
Written on April 7, 2019