문제를 보면 최단 시간에 대한 이야기가 나오는데 여러 지점간 최단 시간을 구해야 되는 문제라 생각해서 제일 먼저 플로이드-워셜 알고리즘을 떠올렸다. 모든 지점 간의 최단 거리를 미리 구해놓으면 야구르트 아줌마가 지점별 도달 시간을 쉽게 구할 수 있고 내가 해당 시간 안에 도착할 수 있는지도 빠르게 구할 수 있다.
하지만 문제의 제약 조건을 확인하면 정점 $V$의 조건이 $(1 \leq V \leq 10000)$ 이므로 시간 복잡도가 $O(N^3)$인 플로이드-워셜을 쓰기에는 부적절하다는 것을 할 수 있다.
로 하고 1부터 9번째 지점까지 돌면서 v[cur]에서 v[i]로 이동할 수 없으면 d[i]를 -1로 바꾸고,
이동할 수 있으면 d[i]는 현재 노드에 도착한 시간인 d[cur]에 dist를 더해주고 cur를 i로 바꿔 이동해주었다. 이 때 오버플로우가 발생할 수 있어 long long 형식으로 저장해주어야 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
vector<int> v(10); vector<ll> d(10, 0); for (int& i : v) cin >> i; int cur = 0; for (int i = 1; i < 10; i++) { ll dist = Dijkstra(v[cur] - 1, v[i] - 1); // v[cur] -> v[i]로 이동할 수 없을 때 if (dist == INF) { d[i] = -1; } // v[cur] -> v[i]로 이동할 수 있으므로 v[i]로 이동한다. else { d[i] = d[cur] + dist; cur = i; } }
각 지점별로 야쿠르트 아줌마의 도착 시간을 구했다면 내 위치로부터 각 지점까지 최단 시간을 구하고 해당 지점에 갈 수 있고, 야구르트 아줌마와 같은 시간 혹은 이전 시간에 도착했다면 ans 벡터에 넣어주었다.
이후 ans를 정렬하여 번호가 가장 작은 정점을 출력하면 답을 얻을 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
int me; cin >> me; vector<int> ans; for (int i = 0; i < 10; i++) {
// 야쿠르트 아줌마가 가지 않는 곳은 무시 if (d[i] == -1) continue; // 야쿠르트 아줌마보다 일찍 갈 수 있는지 확인한다. if (Dijkstra(me - 1, v[i] - 1) <= d[i]) ans.push_back(v[i]); } sort(ans.begin(), ans.end());
if (ans.empty()) cout << -1; else cout << ans.front();