기능 : 출발 노드와 모든 노드간의 최단 거리 탐색
특징 : 에지는 모두 양수
시간 복잡도 : O(ElogV) - V는 노드 수, E는 에지 수
1. 인접 리스트로 그래프 구현하기
배열의 자료형은 (노드, 가중치)로 선언
2. 최단 거리 배열 초기화하기
출발 노드는 0, 이외의 노드를 무한으로 초기화
fill 함수는 O(N)이라서 무겁다..
memset을 사용하자
0x3f, 0x7f (제한이 더 크다면)
보통은 0x3f
3. 값이 가장 작은 노드 고르기
최단 거리 배열에서 현재 값이 가장 작은 노드를 고름
4. 최단 거리 배열 업데이트하기
선택된 노드에 연결된 에지의 값으로 다른 노드의 값을 업데이트.
"선택 노드"의 최단 거리 배열의 값 + 에지 가중치
"연결 노드"의 최단 거리 배열의 값
中 최소값
5. 3, 4 과정을 반복해 최단 거리 배열을 완성
4에서 선택 노드가 될 때 다시 선택되지 않도록 '방문 배열'을 만들어 처리
모든 노드가 선택되면 최단 거리 배열 완성
다익스트라 알고리즘은 출발 노드와 도착 노드의 간의
최단거리를 구하는 알고리즘이 아니다.
출발 노드와 이외의 모든 노드 간의 최단 거리이다.
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
우선순위 큐는 priority_queue<자료형, 구현체, 비교 연산자>로 정의
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
74
|
#include <iostream>
#include <vector>
#include <queue>
#include <limits.h>
using namespace std;
typedef pair<int, int> edge;
// 그래프 정보 저장 인접 리스트
vector<vector<edge>> mlist;
// 최단 거리 저장 배열
vector<int> mdistance;
// 방문 배열
vector<bool> visited;
// greater을 해야 최소값 힙, 오름차순 정렬
//priority_queue <pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
priority_queue <edge, vector<edge>, greater<edge>> q;
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int v, e, k;
cin >> v >> e >> k;
mdistance.resize(v + 1);
fill(mdistance.begin(), mdistance.end(), INT_MAX);
visited.resize(v + 1);
fill(visited.begin(), visited.end(), false);
mlist.resize(v + 1);
for (int i = 0; i < e; i++)
{
int u, v, w;
cin >> u >> v >> w;
mlist[u].push_back(make_pair(v, w));
}
q.push(make_pair(0, k));
mdistance[k] = 0;
while (!q.empty())
{
edge current = q.top();
q.pop();
int c_v = current.second;
if (visited[c_v])
continue;
visited[c_v] = true;
for (int i = 0; i < mlist[c_v].size(); i++)
{
edge tmp = mlist[c_v][i];
int next = tmp.first;
int value = tmp.second;
if (mdistance[next] > mdistance[c_v] + value)
{
mdistance[next] = value + mdistance[c_v];
q.push(make_pair(mdistance[next], next));
}
}
}
for (int i = 1; i <= v; i++)
{
if (visited[i])
cout << mdistance[i] << '\n';
else
cout << "INF" << '\n';
}
return 0;
}
|
cs |
<직접 구현 다익스트라>
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 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | #include <iostream> #include <vector> #include <cstring> using namespace std; struct info { int node; int weight; }; bool operator < (const info& a, const info& b) { return a.weight > b.weight; } // 서로 다른 두 정점 사이에 여러 개의 간선이 존재 // Heap의 크기는 간선 개수 info Heap[300010]; int genzai = 0; void Heap_push(info data) { int idx = ++genzai; Heap[idx] = data; while ((idx != 1) && Heap[idx / 2] < data) { swap(Heap[idx], Heap[idx / 2]); idx = idx / 2; } } info Heap_pop() { info result = Heap[1]; Heap[1] = Heap[genzai]; genzai--; int parent = 1; int child; while (true) { child = parent * 2; if (child + 1 <= genzai && Heap[child] < Heap[child + 1]) child++; if (child > genzai || Heap[child] < Heap[parent]) break; swap(Heap[parent], Heap[child]); parent = child; } return result; } vector<vector<info>> mlist; int mdist[20004]; bool visited[20004]; int main() { ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); int v, e, k; cin >> v >> e >> k; memset(mdist, 0x3f, sizeof(mdist)); memset(visited, false, sizeof(visited)); mlist.resize(v + 1); for (int i = 0; i < e; i++) { int u, v, w; cin >> u >> v >> w; mlist[u].push_back({v, w}); } genzai = 0; // 시작점 0 push Heap_push({ k, 0 }); mdist[k] = 0; while (genzai != 0) { info now = Heap_pop(); int c_v = now.node; if (visited[c_v]) continue; visited[c_v] = true; for (int i = 0; i < mlist[c_v].size(); i++) { info tmp = mlist[c_v][i]; int next = tmp.node; int w = tmp.weight; if (mdist[next] > mdist[c_v] + w) { mdist[next] = mdist[c_v] + w; Heap_push({ next, mdist[next] }); } } } for (int i = 1; i <= v; i++) { if (visited[i]) cout << mdist[i] << '\n'; else cout << "INF" << '\n'; } return 0; } | cs |
https://www.acmicpc.net/problem/1916
1916번: 최소비용 구하기
첫째 줄에 도시의 개수 N(1 ≤ N ≤ 1,000)이 주어지고 둘째 줄에는 버스의 개수 M(1 ≤ M ≤ 100,000)이 주어진다. 그리고 셋째 줄부터 M+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그
www.acmicpc.net
똑같은 문제