본문 바로가기

알고리즘(Algorithm)

[C++] 파티 (1238번)

파티

한국어   
 
시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 128 MB 38985 19628 13169 48.141%

문제

N개의 숫자로 구분된 각각의 마을에 한 명의 학생이 살고 있다.

어느 날 이 N명의 학생이 X (1 ≤ X ≤ N)번 마을에 모여서 파티를 벌이기로 했다. 이 마을 사이에는 총 M개의 단방향 도로들이 있고 i번째 길을 지나는데 Ti(1 ≤ Ti ≤ 100)의 시간을 소비한다.

각각의 학생들은 파티에 참석하기 위해 걸어가서 다시 그들의 마을로 돌아와야 한다. 하지만 이 학생들은 워낙 게을러서 최단 시간에 오고 가기를 원한다.

이 도로들은 단방향이기 때문에 아마 그들이 오고 가는 길이 다를지도 모른다. N명의 학생들 중 오고 가는데 가장 많은 시간을 소비하는 학생은 누구일지 구하여라.

입력

첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 10,000), X가 공백으로 구분되어 입력된다. 두 번째 줄부터 M+1번째 줄까지 i번째 도로의 시작점, 끝점, 그리고 이 도로를 지나는데 필요한 소요시간 Ti가 들어온다. 시작점과 끝점이 같은 도로는 없으며, 시작점과 한 도시 A에서 다른 도시 B로 가는 도로의 개수는 최대 1개이다.

모든 학생들은 집에서 X에 갈수 있고, X에서 집으로 돌아올 수 있는 데이터만 입력으로 주어진다.

출력

첫 번째 줄에 N명의 학생들 중 오고 가는데 가장 오래 걸리는 학생의 소요시간을 출력한다.


문제풀이

처음에 플로이드로 풀어야 하나 고민했지만, single source to all, 즉 한 노드에서 시작하여 모든 노드로의 최단거리를 찾아야 해서 다익스트라 알고리즘을 사용하였다.

갈 때 최단경로, 올 때 최단경로를 구해야한다.

 

갈 때는 all source to single 이므로 플로이드로 풀어야 하나 생각했는데, 방향이 단방향이므로 거꾸로 뒤집어 버린뒤 도착지에서 모든 학생들의 집으로 가는것을 구해버리면 된다. 뒤집어 버리면 single source to all이 되어버리기 때문이다.

그래서 다익스트라를 두번 돌려주면 끝이다.

 

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

int n, m, x;
vector<vector<pair<int, int>>> v1(1001), v2(1001);
int arr1[1001], arr2[1001];

void dijkstra(vector<vector<pair<int, int>>>& v, int arr[]) {
    // to, value
    priority_queue<pair<int, int>> pq;
    pq.push({0, x});
    int visited[1001] = {0, };

    while(!pq.empty()) {
        int value = -pq.top().first;
        int node = pq.top().second;
        pq.pop();

        if(visited[node]) continue;
        visited[node] = 1;

        for(int i=0; i<v[node].size(); i++) {
            if(arr[v[node][i].first] == 0) arr[v[node][i].first] = value+v[node][i].second;
            else arr[v[node][i].first] = min(arr[v[node][i].first], value+v[node][i].second);
            pq.push({-arr[v[node][i].first], v[node][i].first});
        }
    }
}

int main() {
    cin >> n >> m >> x;
    for(int i=0; i<m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        v1[a].push_back({b, c});
        v2[b].push_back({a, c});
    }

    dijkstra(v1, arr1);
    dijkstra(v2, arr2);

    int answer = 0;
    for(int i=1; i<=1000; i++) {
        if(arr1[i] != 0 && arr2[i] != 0 && i!= x) answer = max(answer, arr1[i] + arr2[i]);
    }
    cout << answer;
    return 0;
}

'알고리즘(Algorithm)' 카테고리의 다른 글

[C++] 암호해독기 (17176번)  (0) 2023.09.04
[C++] 피자 굽기 (1756번)  (0) 2023.08.16
[C++] 감소하는 수 (1038번)  (0) 2023.07.08
[C++] 이차원 배열과 연산 (17140번)  (0) 2023.06.27
[C++] 감시 (15683번)  (0) 2023.06.24