성능 요약
메모리: 56.8 MB, 시간: 90.36 ms
구분
코딩테스트 연습 > 2022 KAKAO TECH INTERNSHIP
채점결과
정확성: 100.0
합계: 100.0 / 100.0
제출 일자
2023년 11월 6일 19:19:4
문제 설명
XX산은 n
개의 지점으로 이루어져 있습니다. 각 지점은 1부터 n
까지 번호가 붙어있으며, 출입구, 쉼터, 혹은 산봉우리입니다. 각 지점은 양방향 통행이 가능한 등산로로 연결되어 있으며, 서로 다른 지점을 이동할 때 이 등산로를 이용해야 합니다. 이때, 등산로별로 이동하는데 일정 시간이 소요됩니다.
등산코스는 방문할 지점 번호들을 순서대로 나열하여 표현할 수 있습니다.
예를 들어 1-2-3-2-1
으로 표현하는 등산코스는 1번지점에서 출발하여 2번, 3번, 2번, 1번 지점을 순서대로 방문한다는 뜻입니다.
등산코스를 따라 이동하는 중 쉼터 혹은 산봉우리를 방문할 때마다 휴식을 취할 수 있으며, 휴식 없이 이동해야 하는 시간 중 가장 긴 시간을 해당 등산코스의 intensity
라고 부르기로 합니다.
당신은 XX산의 출입구 중 한 곳에서 출발하여 산봉우리 중 한 곳만 방문한 뒤 다시 원래의 출입구로 돌아오는 등산코스를 정하려고 합니다. 다시 말해, 등산코스에서 출입구는 처음과 끝에 한 번씩, 산봉우리는 한 번만 포함되어야 합니다.
당신은 이러한 규칙을 지키면서 intensity
가 최소가 되도록 등산코스를 정하려고 합니다.
다음은 XX산의 지점과 등산로를 그림으로 표현한 예시입니다.
- 위 그림에서 원에 적힌 숫자는 지점의 번호를 나타내며, 1, 3번 지점에 출입구, 5번 지점에 산봉우리가 있습니다. 각 선분은 등산로를 나타내며, 각 선분에 적힌 수는 이동 시간을 나타냅니다. 예를 들어 1번 지점에서 2번 지점으로 이동할 때는 3시간이 소요됩니다.
위의 예시에서 1-2-5-4-3
과 같은 등산코스는 처음 출발한 원래의 출입구로 돌아오지 않기 때문에 잘못된 등산코스입니다. 또한 1-2-5-6-4-3-2-1
과 같은 등산코스는 코스의 처음과 끝 외에 3번 출입구를 방문하기 때문에 잘못된 등산코스입니다.
등산코스를 3-2-5-4-3
과 같이 정했을 때의 이동경로를 그림으로 나타내면 아래와 같습니다.
이때, 휴식 없이 이동해야 하는 시간 중 가장 긴 시간은 5시간입니다. 따라서 이 등산코스의 intensity
는 5입니다.
등산코스를 1-2-4-5-6-4-2-1
과 같이 정했을 때의 이동경로를 그림으로 나타내면 아래와 같습니다.
이때, 휴식 없이 이동해야 하는 시간 중 가장 긴 시간은 3시간입니다. 따라서 이 등산코스의 intensity
는 3이며, 이 보다 intensity
가 낮은 등산코스는 없습니다.
XX산의 지점 수 n
, 각 등산로의 정보를 담은 2차원 정수 배열 paths
, 출입구들의 번호가 담긴 정수 배열 gates
, 산봉우리들의 번호가 담긴 정수 배열 summits
가 매개변수로 주어집니다. 이때, intensity
가 최소가 되는 등산코스에 포함된 산봉우리 번호와 intensity
의 최솟값을 차례대로 정수 배열에 담아 return 하도록 solution 함수를 완성해주세요. intensity
가 최소가 되는 등산코스가 여러 개라면 그중 산봉우리의 번호가 가장 낮은 등산코스를 선택합니다.
제한사항
- 2 ≤
n
≤ 50,000 n
- 1 ≤paths
의 길이 ≤ 200,000paths
의 원소는[i, j, w]
형태입니다.i
번 지점과j
번 지점을 연결하는 등산로가 있다는 뜻입니다.w
는 두 지점 사이를 이동하는 데 걸리는 시간입니다.- 1 ≤
i
<j
≤n
- 1 ≤
w
≤ 10,000,000 - 서로 다른 두 지점을 직접 연결하는 등산로는 최대 1개입니다.
- 1 ≤
gates
의 길이 ≤n
- 1 ≤
gates
의 원소 ≤n
gates
의 원소는 해당 지점이 출입구임을 나타냅니다.
- 1 ≤
- 1 ≤
summits
의 길이 ≤n
- 1 ≤
summits
의 원소 ≤n
summits
의 원소는 해당 지점이 산봉우리임을 나타냅니다.
- 1 ≤
- 출입구이면서 동시에 산봉우리인 지점은 없습니다.
gates
와summits
에 등장하지 않은 지점은 모두 쉼터입니다.- 임의의 두 지점 사이에 이동 가능한 경로가 항상 존재합니다.
- return 하는 배열은
[산봉우리의 번호, intensity의 최솟값]
순서여야 합니다.
입출력 예
n | paths | gates | summits | result |
---|---|---|---|---|
6 | [[1, 2, 3], [2, 3, 5], [2, 4, 2], [2, 5, 4], [3, 4, 4], [4, 5, 3], [4, 6, 1], [5, 6, 1]] | [1, 3] | [5] | [5, 3] |
7 | [[1, 4, 4], [1, 6, 1], [1, 7, 3], [2, 5, 2], [3, 7, 4], [5, 6, 6]] | [1] | [2, 3, 4] | [3, 4] |
7 | [[1, 2, 5], [1, 4, 1], [2, 3, 1], [2, 6, 7], [4, 5, 1], [5, 6, 1], [6, 7, 1]] | [3, 7] | [1, 5] | [5, 1] |
5 | [[1, 3, 10], [1, 4, 20], [2, 3, 4], [2, 4, 6], [3, 5, 20], [4, 5, 6]] | [1, 2] | [5] | [5, 6] |
입출력 예 설명
입출력 예 #1
문제 예시와 같습니다. 등산코스의 intensity
가 최소가 되는 산봉우리 번호는 5, intensity
의 최솟값은 3이므로 [5, 3]
을 return 해야 합니다.
입출력 예 #2
XX산의 지점과 등산로를 그림으로 표현하면 아래와 같습니다.
가능한 intensity
의 최솟값은 4이며, intensity
가 4가 되는 등산코스는 1-4-1
과 1-7-3-7-1
이 있습니다. intensity
가 최소가 되는 등산코스가 여러 개이므로 둘 중 산봉우리의 번호가 낮은 1-7-3-7-1
을 선택합니다. 따라서 [3, 4]
를 return 해야 합니다.
입출력 예 #3
XX산의 지점과 등산로를 그림으로 표현하면 아래와 같습니다.
가능한 intensity
의 최솟값은 1이며, 그때의 등산코스는 7-6-5-6-7
입니다. 따라서 [5, 1]
를 return 해야 합니다.
7-6-5-4-1-4-5-6-7
과 같은 등산코스는 산봉우리를 여러 번 방문하기 때문에 잘못된 등산코스입니다.
입출력 예 #4
XX산의 지점과 등산로를 그림으로 표현하면 아래와 같습니다.
가능한 intensity
의 최솟값은 6, 그때의 등산코스는 2-4-5-4-2
입니다. 따라서 [5, 6]
을 return 해야 합니다.
코드
#include <string>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <iostream>
const int MAX = 50001;
using namespace std;
bool isGate[MAX];
bool isSummit[MAX];
int dist[MAX];
/**
1. 출입구와 목적지가 정해져있다.
2. intesity가 최소, 즉, 가중치를 최소로 하는 경로를 찾는다.
=> 다익스트라 알고리즘
올라갈 때 가중치가 제일 낮으면 내려갈 때도 해당 경로를 똑같이 사용하면 된다 -> 올라가는 것과 내려가는 것을 따로 계산할 필요 X
출입구부터 시작해서 갈 수 있는 경로 중 발견된 경로 중 가장 작은 가중치를 가지고 목적지까지 도달 -> 우선순위 큐 사용
출입구 어디서부터 시작하든 해당 목적지에 도착했을 때 가중치가 더 큰 것이 존재하면 굳이 해당 출입구부터 시작한 경우를 저장할 필요가 없음
-> 공통된 최소 거리 저장 배열을 사용
**/
//다익스트라 알고리즘
vector<int> Dijkstra(vector<pair<int, int>> graph[MAX], int n, vector<int> &gates) {
vector<vector<int>> result;
//가중치, 코스 번호로 우선순위 결정
priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> pq;
fill_n(dist, MAX, -1);
//출입구 간 이동 제거 및 큐에 삽입
for (int gate : gates) {
isGate[gate] = true;
pq.push({ 0, gate });
}
int w, k;
while (!pq.empty()) {
w = pq.top()[0];
k = pq.top()[1];
pq.pop();
//꼭대기에 도착한 경우 결과를 저장
if (isSummit[k]) {
result.push_back({ w, k });
continue;
}
for (pair<int, int> node : graph[k]) {
//출입구면 제외
if (isGate[node.first])
continue;
int wt = max(w, node.second);
//가중치 갱신이 안됐거나 더 낮은 가중치라면 갱신
if (dist[node.first] == -1 || wt < dist[node.first]) {
dist[node.first] = wt;
pq.push({ wt, node.first });
}
}
}
//가중치, 산봉우리 번호 오름차순으로 정렬
sort(result.begin(), result.end());
reverse(result[0].begin(), result[0].end());
return result[0];
}
vector<int> solution(int n, vector<vector<int>> paths, vector<int> gates, vector<int> summits) {
vector<int> answer = { n, 987654321 };
//경로 저장용 벡터
vector<pair<int, int>> graph[MAX];
int x, y, w;
for (vector<int> path : paths) {
x = path[0], y = path[1], w = path[2];
graph[x].push_back(make_pair(y, w));
graph[y].push_back(make_pair(x, w));
}
//꼭대기인 곳을 저장
for (int summit : summits) {
isSummit[summit] = true;
}
answer = Dijkstra(graph, n, gates);
return answer;
}
테스트 결과
'코딩테스트' 카테고리의 다른 글
[level 3] 블록 이동하기 - 60063 (0) | 2023.11.14 |
---|---|
[level 3] [1차] 추석 트래픽 - 17676 (0) | 2023.11.13 |
[level 3] 불량 사용자 - 64064 (1) | 2023.11.11 |
[level 2] 스킬트리 - 49993 (0) | 2023.11.11 |
[level 2] 주차 요금 계산 - 92341 (0) | 2023.11.07 |