본문 바로가기

그래프/다익스트라

다익스트라

기능 : 출발 노드와 모든 노드간의 최단 거리 탐색

특징 : 에지는 모두 양수

시간 복잡도 : 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, 0x3fsizeof(mdist));
    memset(visited, falsesizeof(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

똑같은 문제

'그래프 > 다익스트라' 카테고리의 다른 글

전송 시간  (0) 2024.08.03
물류 허브  (0) 2024.01.30
간담회 참석  (1) 2024.01.29