[HackerRank] Dijkstra: Shortest Reach 2
HackerRank 알고리즘 문제 풀이
분류
Practice > Algorithms > Graph Theory
문제 링크 : https://www.hackerrank.com/challenges/dijkstrashortreach/problem
풀이
무향(양방향) 그래프의 연결 정보가 주어질 때 시작점(s)에서부터 각각의 정점을 방문하는데 필요한 최소 비용을 구하는 문제이다. 이 비용은 다익스트라 알고리즘을 사용하여 구할 수 있는데(dist : 각 노드를 방문하는데 드는 최소 비용) 우선순위 큐를 활용하여 구현하였다.
방문할 수 없는 위치는 -1로 표시하고 시작점(s)는 결과에서 제외시킨다.
한 가지 특이점이 있다면 작성한 코드에는 시간 초과를 일으킬만한 문제가 없는 것 같은데 시간 초과가 발생하였다. edges를 adj로 재구성하는 것이 시간을 잡아서 그럴 수도 있을 것 같기는 한데 입력되는 간선이 최대 가 되면서 입출력에 시간을 많이 소비하는 문제일 수도 있을 것 같아 main
영역에 ios::sync_with_stdio(false), cin.tie(nullptr);
코드를 한 줄 넣어주고 통과되었다.
소스 코드
#include <bits/stdc++.h>
using namespace std;
vector<string> split_string(string);
// Complete the shortestReach function below.
struct Node {
int dest;
int cost;
bool operator<(const Node& other) const {
return cost > other.cost;
}
};
vector<int> shortestReach(int n, vector<vector<int>> edges, int s) {
const int INF = (int)3e8;
vector<int> dist(n + 1, INF), ans;
vector<vector<Node>> adj(n + 1);
for (const vector<int> edge : edges) {
adj[edge[0]].push_back({edge[1], edge[2]});
adj[edge[1]].push_back({edge[0], edge[2]});
}
dist[s] = 0;
priority_queue<Node> pq;
pq.push({s, 0});
while (!pq.empty()) {
Node now = pq.top();
pq.pop();
if (now.cost > dist[now.dest]) continue;
for (const Node& next : adj[now.dest]) {
if (dist[next.dest] > next.cost + now.cost) {
dist[next.dest] = next.cost + now.cost;
pq.push({next.dest, dist[next.dest]});
}
}
}
for (int i = 1; i <= n; ++i) {
if (i == s) continue;
if (dist[i] == INF) {
ans.push_back(-1);
}
else {
ans.push_back(dist[i]);
}
}
return ans;
}
int main()
{
ios::sync_with_stdio(false), cin.tie(nullptr);
ofstream fout(getenv("OUTPUT_PATH"));
int t;
cin >> t;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
for (int t_itr = 0; t_itr < t; t_itr++) {
string nm_temp;
getline(cin, nm_temp);
vector<string> nm = split_string(nm_temp);
int n = stoi(nm[0]);
int m = stoi(nm[1]);
vector<vector<int>> edges(m);
for (int i = 0; i < m; i++) {
edges[i].resize(3);
for (int j = 0; j < 3; j++) {
cin >> edges[i][j];
}
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
int s;
cin >> s;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
vector<int> result = shortestReach(n, edges, s);
for (int i = 0; i < result.size(); i++) {
fout << result[i];
if (i != result.size() - 1) {
fout << " ";
}
}
fout << "\n";
}
fout.close();
return 0;
}
vector<string> split_string(string input_string) {
string::iterator new_end = unique(input_string.begin(), input_string.end(), [] (const char &x, const char &y) {
return x == y and x == ' ';
});
input_string.erase(new_end, input_string.end());
while (input_string[input_string.length() - 1] == ' ') {
input_string.pop_back();
}
vector<string> splits;
char delimiter = ' ';
size_t i = 0;
size_t pos = input_string.find(delimiter);
while (pos != string::npos) {
splits.push_back(input_string.substr(i, pos - i));
i = pos + 1;
pos = input_string.find(delimiter, i);
}
splits.push_back(input_string.substr(i, min(pos, input_string.length()) - i + 1));
return splits;
}