[백준 C++] 1653번 최단경로
백준 1653번 최단경로 c++로 풀이
[백준 C++] 1653번 최단경로
1753번: 최단경로
문제 요약
문제
방향그래프가 주어지면 주어진 시작점에서 다른 모든 정점으로의 최단 경로를 구하는 프로그램을 작성하시오. 단, 모든 간선의 가중치는 10 이하의 자연수이다.
사용 알고리즘
다익스트라
입출력
- 입력: 첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1 ≤ V ≤ 20,000, 1 ≤ E ≤ 300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1 ≤ K ≤ V)가 주어진다. 셋째 줄부터 E개의 줄에 걸쳐 각 간선을 나타내는 세 개의 정수 (u, v, w)가 순서대로 주어진다. 이는 u에서 v로 가는 가중치 w인 간선이 존재한다는 뜻이다. u와 v는 서로 다르며 w는 10 이하의 자연수이다. 서로 다른 두 정점 사이에 여러 개의 간선이 존재할 수도 있음에 유의한다.
- 출력: 첫째 줄부터 V개의 줄에 걸쳐, i번째 줄에 i번 정점으로의 최단 경로의 경로값을 출력한다. 시작점 자신은 0으로 출력하고, 경로가 존재하지 않는 경우에는 INF를 출력하면 된다. ``` 예제1
입력 5 6 1 5 1 1 1 2 2 1 3 3 2 3 4 2 4 5 3 4 6 출력 0 2 3 7 INF
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
## 풀이
다익스트라 알고리즘을 짜면 풀리는 문제이다. 정점과 가중치를 담는 큐를 만든다. 이 큐는 가중치를 기준으로 하는 우선순위 큐여야 한다. 그리고 맨처음에 이 큐에 정점은 k, 가중치는 0인 것을 담고 while문을 시작한다. 가중치가 가장 작은 것을 가져와 그것을 k와의 거리로 정하고 이 노드에서 이어지는 다른 경로의 값도 큐에 넣는다. 이때 큐에 추가하는 가중치는 `방금 큐에서 꺼내온 가중치+노드에서 이어지는 다른 경로의 가중치`로 한다. 이렇게 하면 k노드를 기준으로 가장 가까운 것 부터 거리가 정해지고 정해진 노드를 경유해서 가는 경우까지도 모두 찾게 된다.
## 어려웠던 점
처음에 큐에 가중치를 합한것으로 안하고 그냥 현재 노드에서 다른 경로의 가중치만을 넣어서 틀렸다.
## 배운 점 / 느낀 점
왜인지 다익스트라를 쉬운 알고리즘이라고 생각했는데 생각보다 어려웠다. 확실히 기억해둬야 겠다. 내림차순 우선순위 큐도 기억해둬야 겠다.
## 전체 코드
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
int v, e, k;
vector<bool> visit;
vector<vector<pair<int,int>>> g;
vector<int> d;
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> q;
int infity = 1e9;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> v >> e >> k;
visit = vector<bool>(v+1);
d = vector<int>(v+1, infity);
g = vector<vector<pair<int,int>>>(v+1, vector<pair<int,int>>());
q = priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>>();
for(int i = 0; i < e; i++){
int u, vv, w;
cin >> u >> vv >> w;
auto it = find_if(g[u].begin(), g[u].end(), [vv](const pair<int,int>& p) {
return p.second == vv;
});
if(it != g[u].end()){
it->first = min(it->first, w);
}
else{
g[u].push_back({w,vv});
}
}
d[k] = 0;
q.push({0, k});
while(!q.empty()){
int vv = q.top().second;
int w = q.top().first;
q.pop();
if(visit[vv]){
continue;
}
visit[vv] = true;
for (int i = 0; i < g[vv].size(); i++) {
if(visit[g[vv][i].second]) continue;
d[g[vv][i].second] = min(d[g[vv][i].second], g[vv][i].first+d[vv]);
q.push({d[g[vv][i].second], g[vv][i].second});
}
}
for (int i = 1; i <= v; i++) {
if(d[i] == infity){
cout << "INF\n";
}
else{
cout << d[i] << '\n';
}
}
return 0;
}
This post is licensed under CC BY 4.0 by the author.