[BOJ][백준 1753] 최단경로 구하기 - C++
2023. 5. 18. 14:00ㆍIT이모) 알고리즘 문제풀이/백준 문제풀이
https://www.acmicpc.net/problem/1753
1753번: 최단경로
첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1 ≤ V ≤ 20,000, 1 ≤ E ≤ 300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1 ≤ K ≤ V)가
www.acmicpc.net
백준 사이트의 1753번 문제, 최단경로 구하기 문제다.
본인은 C++로 문제풀이를 진행하였다.
어제 업로드했던 위 문제를 풀고나서 Dijkstra 알고리즘에 대한 복습이 더 필요함이 느껴져서 고른 문제다.
0. 문제 읽기
- 보통 최단경로를 구하는 문제는 BFS(너비 우선 탐색) 알고리즘으로 문제풀이를 하기 마련인데, 이 문제는 간선의 가중치가 주어져있어 Dijkstra 알고리즘을 사용하는 문제다.
- Dijkstra 알고리즘을 사용하여 주어진 그래프에서 한 정점에서 다른 모든 정점까지의 최단 거리를 구하는 문제
1. 문제풀이 아이디어
- 가중치가 있는 그래프에서 최소비용을 구하는 알고리즘인 Dijkstra의 기본 형식이다.
- 참고1) 가중치가 없는 그래프의 최단경로 => BFS 알고리즘 (너비 우선 탐색 알고리즘)
- 참고2) Dijkstra알고리즘은 가중치에 음수가 포함된 경우에는 사용할 수 없다!
- 단방향 그래프이다.
- Dijkstra 알고리즘 구현에는 for문을 사용하는 방법(시간복잡도: O(N^2))과 우선순위 큐를 사용하는 방법(시간복잡도: O(NlogN)) 두가지가 있다.
- 나는 그중에서 우선순위 큐를 사용한 방법으로 문제를 해결하였다.
- 백준 1916번 문제와의 차이점은 딱 경로값 하나를 출력하는지 전부를 출력하는지 차이이다. (그래서 왜 난이도 차이가 나는지 모르겠다)
2. 코드 핵심 부분
1) dijkstra 알고리즘 구현 함수,
기본적인 틀 그대로 사용하여 특별한 점은 없다.
// 다익스트라 알고리즘 구현
void dijkstra(int start) {
// 다익스트라 알고리즘을 위한 초기 세팅
priority_queue<Edge> pq;
for (int i = 1; i <= V; i++)
dist[i] = Max;
int visited[20001] = { 0 };
pq.push({ start, 0 });
dist[start] = 0;
while (!pq.empty()) {
Edge Now = pq.top();
pq.pop();
if (visited[Now.to])
continue;
visited[Now.to] = 1;
for (int i = 0; i < al[Now.to].size(); i++) {
Edge Next = al[Now.to][i];
int ncost = Next.cost + Now.cost;
if (ncost >= dist[Next.to])
continue;
dist[Next.to] = ncost;
pq.push({ Next.to, ncost });
}
}
}
2) 정답을 출력하는 output 함수,
만약 dist 값이 초기 세팅한 Max값 그대로면 경로가 존재하지 않는 경우이기 때문에 INF를 출력하고,
dist값에 변화가 있으면 그 값을 출력해준다.
// 출력을 하는 함수
void output() {
for (int i = 1; i <= V; i++) {
if (dist[i] == Max)
cout << "INF\n";
else
cout << dist[i] << "\n";
}
}
3. 전체 코드
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
#define Max 21e8
struct Edge {
int to;
int cost;
// 비교 연산을 위한 연산자 오버로딩
bool operator < (Edge Next) const {
if (cost < Next.cost)
return false;
if (cost > Next.cost)
return true;
return false;
}
};
// 필요한 전역 변수들
int V, E; // 정점과 간선의 개수
vector<Edge> al[20001]; // 인접 리스트
int st; // 시작 정점
int dist[20001]; // 최단 거리를 저장하는 배열
// 입력을 받는 함수
void input() {
cin >> V >> E >> st; // 정점의 개수, 간선의 개수, 시작 정점을 입력 받음
int from, to, cost;
for (int i = 0; i < E; i++) {
cin >> from >> to >> cost;
al[from].push_back({ to, cost }); // 간선을 인접 리스트에 추가함
}
}
// 다익스트라 알고리즘 구현
void dijkstra(int start) {
// 다익스트라 알고리즘을 위한 초기 세팅
priority_queue<Edge> pq;
for (int i = 1; i <= V; i++)
dist[i] = Max;
int visited[20001] = { 0 };
pq.push({ start, 0 });
dist[start] = 0;
while (!pq.empty()) {
Edge Now = pq.top();
pq.pop();
if (visited[Now.to])
continue;
visited[Now.to] = 1;
for (int i = 0; i < al[Now.to].size(); i++) {
Edge Next = al[Now.to][i];
int ncost = Next.cost + Now.cost;
if (ncost >= dist[Next.to])
continue;
dist[Next.to] = ncost;
pq.push({ Next.to, ncost });
}
}
}
// 출력을 하는 함수
void output() {
for (int i = 1; i <= V; i++) {
if (dist[i] == Max)
cout << "INF\n";
else
cout << dist[i] << "\n";
}
}
// 메인 함수
int main() {
// 입력
input();
// 다익스트라 알고리즘 수행
dijkstra(st);
// 출력
output();
return 0;
}
4. 문제 풀이를 마치며..
하루전에 다익스트라 알고리즘이 생각나지 않아 당황하고
바로 복습을 위해 고른 문제다.
이번에는 잘 풀어낸 것 같아 만족스럽다.
'IT이모) 알고리즘 문제풀이 > 백준 문제풀이' 카테고리의 다른 글
[BOJ][백준 1916] 최소비용 구하기 - C++ (0) | 2023.05.17 |
---|---|
[BOJ][백준 16953] A -> B - C++ (0) | 2023.05.16 |
[BOJ][백준 12919] A와 B 2 - C++ (0) | 2023.05.11 |
[BOJ][백준 13549] 숨바꼭질 3 - C++ (0) | 2023.05.10 |
[BOJ][백준 2668] 숫자고르기 - C++ (0) | 2023.05.09 |