[HackerRank] Dijkstra: Shortest Reach 2

2 분 소요

HackerRank 알고리즘 문제 풀이

분류

Practice > Algorithms > Graph Theory

문제 링크 : https://www.hackerrank.com/challenges/dijkstrashortreach/problem

풀이

무향(양방향) 그래프의 연결 정보가 주어질 때 시작점(s)에서부터 각각의 정점을 방문하는데 필요한 최소 비용을 구하는 문제이다. 이 비용은 다익스트라 알고리즘을 사용하여 구할 수 있는데(dist : 각 노드를 방문하는데 드는 최소 비용) 우선순위 큐를 활용하여 구현하였다.

방문할 수 없는 위치는 -1로 표시하고 시작점(s)는 결과에서 제외시킨다.

한 가지 특이점이 있다면 작성한 코드에는 시간 초과를 일으킬만한 문제가 없는 것 같은데 시간 초과가 발생하였다. edgesadj로 재구성하는 것이 시간을 잡아서 그럴 수도 있을 것 같기는 한데 입력되는 간선이 최대 가 되면서 입출력에 시간을 많이 소비하는 문제일 수도 있을 것 같아 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;
}