Coding Test/BOJ
# 1753. 최단경로
soyw906
2023. 1. 29. 22:44
관련 알고리즘 : 다익스트라(Dijkstra)
문제 링크 : 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
문제 풀이
▶ 문제 조건
- 정점의 개수 V (1 <= V <= 20,000)
- 간선의 개수 E (1 <= E <= 300,000)
- 간선 (u, v, w) (w: u→v로 가는 가중치 w인 간선), (u != v)
- 서로 다른 두 정점 사이 여러 개의 간선 존재 가능
- 모든 간선의 가중치 → 10 이하의 자연수
문제의 조건을 보면, 주어진 시작점에서 i번 정점까지의 최단거리를 구해야 함을 알 수 있다.
최단경로를 구하는 알고리즘에는 크게 3가지가 존재하는데,
- 다익스트라 알고리즘
- 벨만-포드 알고리즘
- 플로이드-워셜 알고리즘
✔ 이 문제에서는 하나의 정점에서 모든 정점까지의 최단경로를 구해야 하고, 간선에 음의 가중치가 없기 때문에
다익스트라 알고리즘을 이용하여 해결해야 함을 알 수 있다.
✔ 다익스트라는 배열로 구하는 방법과, 우선순위 큐를 이용하는 방법 이렇게 2가지가 존재하는데,
배열로 구현 시 시간 복잡도가 O(V^2)이고, 우선순위 큐를 이용하면 시간 복잡도가 O(E+Vlog(V))로 배열에 비해
시간 단축 정도가 크기 때문에 우선순위 큐를 이용하여 시간 초과를 해결할 수 있다.
더보기
<다익스트라 알고리즘의 흐름>
- 시작 노드와 직접적으로 연결된 모든 정점들의 거리 업데이트
- 시작 노드를 방문한 노드로 체크
- 시작 노드와 연결되어 있는 정점들 중, 비용이 가장 적게 드는 정점 선택
- 해당 정점을 방문한 노드로 체크
- 3번 과정에 의해 갱신될 수 있는 정점들의 거리 갱신
- 위의 과정 반복
C++ 코드
#include<iostream>
#include<queue>
#include<vector>
#define endl "\n"
#define MAX 20010
#define INF 987654321
using namespace std;
int v, e, start; // 정점 v, 간선 e, 시작점 start
int d[MAX]; // 최소 비용 배열
vector<pair<int, int>> vertex[MAX]; // pair<간선, 비용>
void input()
{
cin >> v >> e >> start;
for(int i = 0; i < e; i++)
{
int u, v, w;
cin >> u >> v >> w;
vertex[u].push_back(make_pair(v, w));
}
for(int i = 1; i <= v; i++) d[i] = INF; // 배열 초기화
}
void dijkstra()
{
priority_queue<pair<int, int>> PQ;
PQ.push(make_pair(0, start)); // pair<비용, 도착 노드>
d[start] = 0; // 시작 노드에서 시작 노드로 가는 비용 0
while(PQ.empty() == 0)
{
int cost = -PQ.top().first;
// 비용 값이 음수화 된 상태로(최소 비용부터 top에 옴) 정렬되어 있으므로 다시 양수화하여 사용
int current = PQ.top().second;
PQ.pop();
for(int i = 0; i < vertex[current].size(); i++)
{
int next = vertex[current][i].first;
int next_cost = vertex[current][i].second;
if(d[next] > cost + next_cost) // 최소비용 갱신
{
d[next] = cost + next_cost;
PQ.push(make_pair(-d[next], next));
}
}
}
for(int i = 1; i <= v; i++)
{
if(d[i] == INF) cout << "INF" << endl;
else cout << d[i] << endl;
}
}
void solve()
{
input();
dijkstra();
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
solve();
return 0;
}