N
(백준 c++)특정한 최단 경로 본문
문제
방향성이 없는 그래프가 주어진다. 세준이는 1번 정점에서 N번 정점으로 최단 거리로 이동하려고 한다. 또한 세준이는 두 가지 조건을 만족하면서 이동하는 특정한 최단 경로를 구하고 싶은데, 그것은 바로 임의로 주어진 두 정점은 반드시 통과해야 한다는 것이다.
세준이는 한번 이동했던 정점은 물론, 한번 이동했던 간선도 다시 이동할 수 있다. 하지만 반드시 최단 경로로 이동해야 한다는 사실에 주의하라. 1번 정점에서 N번 정점으로 이동할 때, 주어진 두 정점을 반드시 거치면서 최단 경로로 이동하는 프로그램을 작성하시오.
입력
첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄에 걸쳐서 세 개의 정수 a, b, c가 주어지는데, a번 정점에서 b번 정점까지 양방향 길이 존재하며, 그 거리가 c라는 뜻이다. (1 ≤ c ≤ 1,000) 다음 줄에는 반드시 거쳐야 하는 두 개의 서로 다른 정점 번호 v1과 v2가 주어진다. (v1 ≠ v2, v1 ≠ N, v2 ≠ 1)
출력
첫째 줄에 두 개의 정점을 지나는 최단 경로의 길이를 출력한다. 그러한 경로가 없을 때에는 -1을 출력한다.
특정한 경로 v1, v2를 무조건 지나야 한다.
1 -> v1 -> v2 -> N 의 경우와
1 -> v2 -> v1 -> N 의 경우를 구해 답을 찾아내자.
다익스트라 알고리즘을 함수 형태로 빼내서 start와 end를 구할 수 있도록 한다.
dist[end]를 리턴하는데, 이는 start -> end 까지의 최단 경로 값을 나타낸다.
long long ans1과 ans2를 선언해 0으로 초기화.
long long인 경우 경로가 없으면 INF인데, 이 값이 int형을 벗어나면 오버플로우가 나기 때문에 틀린 답이 리턴 될 것이다.
ans1은 1 -> v1 -> v2 -> N으로 갈 때 최단 경로,
ans2은 1 -> v2 -> v1 -> N으로 갈 때 최단 경로를 나타낸다.
두 가지 경우의 최단 경로를 모두 구한 후,
두 값이 INF를 넘지 않으면 둘 중 작은 값을 출력하면 된다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#define INF 1000000000
using namespace std;
vector<pair<int, int>> graph[200001];
int dijkstra(int start, int end){
priority_queue<pair<int, int>> pq;
vector<int> dist(200001, INF);
pq.push(make_pair(0, start));
dist[start] = 0;
while(!pq.empty()){
int cost = -pq.top().first;
int current = pq.top().second;
pq.pop();
if(dist[current] < cost){
continue;
}
for(int i = 0; i < graph[current].size(); i++){
int next = graph[current][i].first;
int nextCost = graph[current][i].second + cost;
if(dist[next] > nextCost){
dist[next] = nextCost;
pq.push(make_pair(-nextCost, next));
}
}
}
return dist[end];
}
int main(void){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N, E, v1, v2;
long long ans1 = 0, ans2 = 0;
priority_queue<pair<int, int>> pq;
cin >> N >> E;
for(int i = 0; i < E; i++){
int a, b, c;
cin >> a >> b >> c;
graph[a].push_back(make_pair(b, c));
graph[b].push_back(make_pair(a, c));
}
cin >> v1 >> v2;
ans1 += dijkstra(1, v1);
ans1 += dijkstra(v1, v2);
ans1 += dijkstra(v2, N);
ans2 += dijkstra(1, v2);
ans2 += dijkstra(v2, v1);
ans2 += dijkstra(v1, N);
if(ans1 >= INF && ans2 >= INF){
cout << -1;
}
else{
cout << min(ans1, ans2);
}
return 0;
}
'백준 알고리즘' 카테고리의 다른 글
(백준 c++)2630 색종이 만들기 (0) | 2021.06.02 |
---|---|
(백준 c++)9370 미확인 도착지 (0) | 2021.05.31 |
(백준 c++)최단 경로 (0) | 2021.05.21 |
(백준 c++)2805 나무 자르기 (0) | 2021.05.04 |
(백준 c++)1654 랜선 자르기 (0) | 2021.05.04 |